• Struts2 学习记录-1--Struts2中的配置文件


    主要涉及3个配置文件:web.xml、struts.xml、struts.properties

    1. web.xml

    任何参与了web应用程序的请求与响应动作,都必须借助web.xml文件来安装这个框架。
    struts2的web.xml配置可以参考 官方文档.
    首先需要配置过滤器:

    <filter>
        <filter-name>struts2</filter-name>
        <!-- struts 2.5及以上版本 -->
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <!-- 拦截所有用户请求 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    如果

    <url-pattern>*.action</url-pattern>
    <url-pattern>*.do</url-pattern>
    

    则只处理以.do.action结尾的请求
    通过以上配置就可以使用struts2了。但除此之外,还可以在filter之中配置如下内容:

    <init-param>
          <!-- 自动加载的系列配置文件 -->
          <param-name>config</param-name>
          <param-value>struts-default.xml,struts-plugin.xml,/WEB-INF/struts.xml </param-value>
    </init-param>
    <init-param>
        <!-- 配置Struts2框架要扫描的包,多个包用逗号分开。 -->  
        <param-name>actionPackages</param-name>  
        <param-value>org.apache.struts2.showcase.person</param-value>  </init-param>  
        <!-- 配置Struts2框架的配置提供者类,多个类用逗号分开 -->  
    <init-param>  
        <param-name>configProviders</param-name>  
        <param-value>com.MyConfigurationProvider</param-value>  
    </init-param> 
    

    或者设置某些属性:

    <filter>
       <filter-name>struts</filter-name>
       <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
       <init-param>
           <param-name>struts.devMode</param-name>
           <param-value>true</param-value>
       </init-param>
    </filter>
    

    2. struts.xml

    Struts2框架的核心配置文件,主要负责管理struts2框架中的action映射和result以及常量属性(或由struts.properties配置)。参考:
    官方 Configuration Elements
    Struts2 配置文件struts.xml和web.xml详解
    默认情况下,Struts2的配置文件名称为struts.xml,且该文件放在src根目录下(即/WEB-INF/classes目录下、src/main/resources)。如果修改了名称或位置,则需要清晰的进行配置,方法即是上文中的filter中的config配置:

    <init-param>  
        <param-name>config</param-name>  
        <param-value>struts-default.xml,struts-plugin.xml,struts/struts.xml</param-value> 
    </init-param> 
    

    struts-default.xml,struts-plugin.xml也必须加上,或者在struts.xml文件中添加include标签将两个文件包括进去。
    或者采用下述配置(?)

    <init-param>  
        <param-name>filterConfig</param-name>  
        <param-value>classpath:struts2/struts.xml</param-value>  
    </init-param>  
    

    struts.xml 配置示例

    <?xml version="1.0" encoding="UTF-8" ?>  
    <!DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
            "http://struts.apache.org/dtds/struts-2.5.dtd">    
    <struts>  
        <!-- 基础配置:常量属性 -->
        <constant name="struts.enable.DynamicMethodInvocation" value="false" />  
        <!-- 开发模式,在web服务器出错时会尽量打印出来 -->
        <constant name="struts.devMode" value="true" />
        <!-- 配置文件修改后是否自动重新部署到服务器,开发阶段可设置为true,否则需要不时重启服务器。-->
        <constant name="struts.configuration.xml.reload" value="true" />    
        <!-- struts2是处理以.do和.action为后缀的请求url的(默认是.action)-->
        <constant name="struts.action.extension" value="do,action"/>
        <!-- 包含其他的struts2配置,file属性是相对/WEB-INF/classes的路径  -->
        <include file="Home.xml"/>
        <!-- 全局异常配置  -->
        <package name="main" namespace="/" extends="struts-default">
            <!--指定一个默认的Action,如果系统没有找到指定的Action,就会指定来调用这个默认的Action -->
            <default-action-ref name="index" />  
            <global-results>
                <result name="error">/error.jsp</result>  
            </global-results>
            <global-exception-mappings>
                <exception-mapping exception="java.lang.Exception" result="error"/>
            </global-exception-mappings>  
        </package>
      
      <package name="employee" extends="struts-default" namespace="/employee">
      <!-- 设置整个包范围内所有Action所要应用的默认拦截器信息。一般不用设置而使用框架默认的即可 -->
        <default-interceptor-ref name="crudStack"/>
          <action name="delete" method="delete"
            class="org.apache.struts2.showcase.action.EmployeeAction" >
            <result name="error">/empmanager/editEmployee.jsp</result>
            <result type="redirect">edit-${currentEmployee.empId}.action</result>
            <!-- 拦截器信息,一般也不设置 -->
            <interceptor-ref name="basicStack"/>
          </action>
      </package>
      <!-- 多继承,json配置 -->
      <package name="employee" extends="struts-default, json-default" namespace="/employee"> 
        <action name="list" method="list" class="org.apache.struts2.showcase.action.EmployeeAction" >
            <result>/empmanager/listEmployees.jsp</result>
            <result type="json">
                <param name="root">employees</param>
            </result>
        </action>
      </package>
    </struts>
    

    特别地,对于返回json的配置(基于 struts2-json-plugin)(参考: stackoverflow例子json-pluginStruts2返回JSON对象的方法总结 ):

    public class Struts2Action extends ActionSupport {
        private String jsonString;
        public String execute() {
            Gson gson = new Gson();
            jsonString = gson.toJson(audioTaggingService.findTagsByName(q));
            return "success";
        }
        //没有getter的属性将不会出现在json中
        public String getJsonString() {
            return jsonString;
        }
        public void setJsonString(String jsonString) {
            this.jsonString = jsonString;
        }
    }
    

    配置xml。注意extends中必须出现json-default,可以没有struts-default(因为json-default继承自它)。
    root指明了要序列化为json的对象。如果action类中只有一个属性,可以不设置root。

    <package name="json" extends="struts-default,json-default" >
      <action name="someJsonAction" class="com.something.Struts2Action">
         <result type="json">
            <param name="noCache">true</param>
            <param name="excludeNullProperties">true</param>
            <param name="root">jsonString</param>
         </result>
      </action>
    </package>
    

    附:返回json还有一种简便的方法,即将生成好的json字符串写入到response中去,返回给前端使用。对实体对象转JSON有许多组件可用,如FastJSON,GSON等。

    public static void writeJson(String json)
        {
            //每次调用都进行初始化
            HttpServletResponse response = ServletActionContext.getResponse();
            response.setContentType("application/json;charset=utf-8");
            try
            {
                response.getWriter().write(json);
                response.getWriter().flush();
                response.getWriter().close();
            }
            catch (IOException e)
            {    e.printStackTrace();    }
        }
    

    3. struts.properties文件

    本文件主要负责配置struts2中大量的属性(struts.xml中的<constant name="" value="">)。
    部分属性:
    struts.locale:默认 en_US,指定 locate 和 encoding schema
    struts.il8n.encoding:设置默认编码集,默认值为 utf-8
    struts.objectFactory:默认值 spring
    struts.objectFactory.spring.autoWire:指定spring框架的自动装配模式,默认值 name(默认根据name属性装配)。可选值为:name/ type/auto/construtor
    struts.multipart.parser 处理multipart/form-data的MIME类型请求框架,默认 jakarta,即 common-fileupload
    struts.multipart.saveDir 保存上传文件的临时路径
    struts.multipart.maxSize允许上传的最大字节数
    struts.action.extension默认为 action,为了支持.do,可设置为 "do,action"

    4.注解式开发

    依赖struts2-convention-plugin。注解与基于xml配置基本是一致的。
    基本无需进行配置,或者只需要极其少量的配置(针对struts.xml)。
    进行全局配置:配置一个名为base,继承自json-default的package,便于后续使用。

    <package name="base" extends="json-default,struts-default">  
            <!-- 这里可以设置一些全局的返回值映射关系等 -->  
    </package> 
    

    然后,在Action类代码中使用注解:

    //若struts.xml中没有配置名为 base 的包,则 “base” 需要写成 "json-default"。如果不是json,则为"struts-default"
    @ParentPackage("base") 
    @Namespace("/watson")  //命名空间
    @Results({  
        @Result(name = "json",type="json", params={"root","msg"})  
    })  //reuslt配置
    public class JsonAction {  
        private Map<String, Object> msg;
        //msg必须有getter方法才能出现在JSON中
        public Map<String, Object> getMsg() {  
            return msg;  
        }
        @Action(value="json")  
        public String json() { 
            msg = new HashMap<String, Object>();          
            msg.put("user", user);  
            return "json";  
        }
    

    基于方法的@Result注解

    @Action(    value="login",  //表示action的请求名称
                results={  //表示结果跳转
                @Result(name="success",location="/success.jsp",type="redirect"), 
                @Result(name="login",location="/login.jsp",type="redirect"), 
                @Result(name="error",location="/error.jsp",type="redirect")  
                },
                //表示拦截器引用
                interceptorRefs={@InterceptorRef("defaultStack"), @InterceptorRef("timer")},
               //异常映射声明 
               exceptionMappings={@ExceptionMapping(exception="java.lang.Exception",result="error")}
        ) 
        public String login() throws Exception {  
            int i = 1/0 ; 
            if ("admin".equals(user.getUsercode()) && "admin".equals(user.getUserpswd())) {
                Map session = ActionContext.getContext().getSession();  
                session.put("session_user", user);
                return "success";  
            } else {  
                return "login";  
            }  
        }  
    

    5.与Spring框架集成的配置

    需要struts2-spring-plugin,参考: Struts2+Spring集成合并
    <constant name="struts.objectFactory" value="spring" />

    1. 方案一,Struts2负责流程,Spring负责对象的创建;Action由Struts2框架负责创建;Service由Spring框架负责创建
      这种情况下,只需要按要求分别配置好Struts2和Spring即可。或者根据需要修改struts.objectFactory.spring.autoWire等配置。
      这个时候使用注解开发,Action类无需使用Spring的@Controller注解,但需加上@Scope("prototype")设为多例
    2. 方案二,Struts2负责流程,Spring负责对象的创建,Action和Service都由Spring框架负责创建。这是常用的集成合并方案
      主要看一下两个框架核心配置文件的和第一种方案的写法区别:
    • struts2.xml的写法:
    <struts>  
         <!-- 注意class的值,这里是Spring中bean的id,是为了在Spring中根据此值进行查找 --> 
         <!-- 写完整包名代表Action还是由Struts管理,action都是多例! -->
        <package name="example" namespace="/user" extends="struts-default">  
            <action name="login" class="loginAction" method="login">  
                <result name="success" type="redirect">/success.jsp</result>  
                <result name="login" type="redirect">/login.jsp</result>  
            </action>
        </package>
    </struts>  
    </span>  
    
    • spring配置文件 applicatinContext.xml的写法:
    <!--这里的id对应上边的class,这里的class才是真正的路径,采用了Spring的根据name自动装配的功能,当然也可以我们手动指定,
       这里需要注意的是,action需要多例创建,而Spring默认为单例创建的,所以需要指定scope="prototype"-->  
        <bean id="loginAction" class="com.ljh.action.LoginAction" autowire="byName" scope="prototype"></bean> 
        <bean id="userService" class="com.ljh.service.UserService" ></bean>  
    </span>
    

    如果都采用注解的方式,Action使用 @Controller注解
    注:
    struts2的单例多例问题

    1. Struts2会对每一个请求,产生一个Action的实例来处理. ---多例
    2. Spring的Ioc容器管理的bean默认是单实例的. ---单例
  • 相关阅读:
    多进程多线程的选择
    MessageBox常用用法
    Ioc 控制反转 实例
    解决 MVC 用户上线下线状态问题
    你不知道的东西! c# == 等于运算符 和 Object.Equals()
    一个明确的目标
    .NET String.Format 方法 线程安全问题
    IEnumerable 接口 实现foreach 遍历 实例
    Android闹钟 AlarmManager的使用*
    @Java四种引用包括强引用,软引用,弱引用,虚引用
  • 原文地址:https://www.cnblogs.com/yes-V-can/p/5895197.html
Copyright © 2020-2023  润新知