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

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

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>

若是java

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

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

<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>

或者设置某些属性:spring

<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配置:apache

<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标签将两个文件包括进去。
或者采用下述配置(?)json

<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对象的方法总结 ):session

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。app

<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默认是单实例的. ---单例