Struts2总结

  前两天去面试,发现面的很失败,比预想的要失败很多,发现问的很多简单的基础的东西都没能答出来,才发现自己之前做东西都只是注意了如何做出来,至于做的时候那些细节都记得有点模糊,所以准备把之前用到的东西稍微整理一下,就从Struts2开始了。

 

  1. 简介:

    现在的基于请求响应模式的应用的框架,基本上都是基于MVC模式的,有以下几个表现逻辑结构:

       控制器: 控制整个框架的各个部件协调工作,调用内部组件去处理相对应的请求。
       业务逻辑层:框架中用于处理具体的业务逻辑的层次,根据不同的用户需求,由开发人员自己在框架上拓展补充。
       数据逻辑层:这一层主要是整个程序的数据的访问,存储,交互等内容。
    其中Struts2主要做的是控制器层,与之类似的还有Struts(已过时),SpringMVC。Struts2虽然看起来是Struts的第二版,但其实与struts没有太大相关系,它是以WebWork为核心发展出来的。
 
  2.原理:
    下图是Struts2官网上面的框架流程图,可以看出Struts2处理过程中主要有四部分内容组成:
    1)Servlet Filter:用户在web.xml中配置的各种过滤器,其中最重要的是StrutsPrepareAndExecuteFilter(2.12之后)或FilterDispatcher(2.12之前),是Struts2的入口。
    2)Struts Core:开始进入Struts2的框架核心代码中。首先调用ActionMapper获取Action信息,然后调用ActionProxy获取具体的Action和过滤器信息。然后ActionProxy将请求交给ActionInvocation,由ActionInvocation调用过滤器和Action。Action返回result并经过Template渲染之后返回给客户端。
    3)Interceptors:用户配置的过滤器,由ActionInvocation调用,实现Action处理前后的处理。
    4)用户创建的内容:主要包括struts.xml,具体的Action和模板,struts.xml是核心配置文件,配置了过滤器,action和result等。Action具体处理业务,Template负责展示。
    
  
  3. 简单使用:
    如果使用Maven,在pom.xml中添加:
 1     <dependency>
 2         <groupId>org.apache.struts</groupId>
 3         <artifactId>struts2-core</artifactId>
 4         <version>2.3.20</version>
 5     </dependency>
 6     <dependency>
 7         <groupId>org.apache.struts</groupId>
 8         <artifactId>struts2-convention-plugin</artifactId>
 9         <version>2.3.20</version>
10     </dependency>

    然后修改web.xml文件:

1   <filter >
2       <filter-name >struts2</ filter-name>
3         < filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class>
4   </filter >
5  
6   <filter-mapping >
7       <filter-name >struts2</ filter-name>
8       <url-pattern >/*</ url-pattern>
9   </filter-mapping >

    添加struts.xml文件:

1     <!-- 包设置,继承自struts-default -->
2     <package name="struts2" namespace="/" extends="struts-default">
3         <!-- action路径及相应Action类,method为相应处理方法,默认为execute -->
4         <action name="login" class="com.zhangyx.struts.controller.Test" method="execute">
5             <!-- result页面 -->
6             <result name="success">/result.jsp</result>
7         </action>
8     </package>

 

     Action代码:

 1 public class Test extends ActionSupport{
 2        private String username ;
 3        private String password ;
 4        public String getUsername() {
 5              return username ;
 6       }
 7        public void setUsername(String username) {
 8              this.username = username;
 9       }
10        public String getPassword() {
11              return password ;
12       }
13        public void setPassword(String password) {
14              this.password = password;
15       }
16        public String execute(){
17              return "success" ;
18       }
19 }

    页面:

login.jsp:
    <form action="login">
          username:<input type="text" name="username" ><br>
          password: <input type="text" name="password"/>< br>
          <input type="submit" value="login" />
       </form>

result.jsp:
        username:${requestScope.username }<br >
        password:${requestScope.password } <br/>

 

  4. 类型转换:

    对于基本类型,如String,Date等类型,struts框架可以使用内部的转换器自动去转换,自定义的对象,就必须使用自己定义的转换器来进行转换。

           建立的配置文件的名字叫做UserAction-conversion.properties,其中前边是Action的名字,后面是“-conversion.properties”。内部是一个键值对。内容如下:
           user=com.zhangyx.converter.UserConverter
    或者是建立全局的类型转换,建立文件xwork-conversion.properties。里面的内容如下:
           com.zhangyx.bean=com.zhangyx.converter.UserConverter
 1 //可以继承两个类,DefaultTypeConverter和StrutsTypeConverter。其中StrutsTypeConverter也是继承了DefaultTypeConverter并进行了封装。
 2 public class UserConverter extends StrutsTypeConverter {
 3     @Override
 4     // 将表单中数据向包装类转换。
 5     public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
 6         if (User.class == arg2) {
 7             User user = new User();
 8             // String数组中存放的是与变量名相同的表单中的数据。名字不同的被排除了。
 9             user.setUsername(arg1[0]);
10             user.setPassword(arg1[1]);
11             return user;
12         }
13         return null;
14     }
15 
16     @Override
17     // 将包装类中数据向视图转换。
18     public String convertToString(Map arg0, Object arg1) {
19         User user = (User) arg1;
20         return "username:" + user.getUsername() + "\n password+"
21                 + user.getPassword();
22     }
23 }

 

  5. 数据校验:
    对于struts2中前台传过来的数据,有时候是不符合我们的要求的,需要在执行Action之前进行数据校验。在ActionSupport中有这么一个方法,validate()方法,这个是ActionSupport类实现Validateable接口的方法。这个方法就是用来在进行业务处理之前进行数据校验的方法。这个方法是在进行赋值之后,运行execute方法之前运行的。如果为自定义处理方法myExecute,单独的校验方法为:myExecuteValidate。
    下边是几个ActionSupport中的方法,用于在校验处理异常数据的方法。
 
        addActionError("actionerror!");//Action级别的错误
        addFieldError("field", "fielderror!");//Field级别错误
        clearErrors();//清除所有错误
        clearActionErrors();//清除Action级别错误
        clearFieldErrors();//清除Field级别错误

    页面上显示校验错误:

     <s:actionerror cssStyle= "color:red"/><!-- 如果有Action级别错误信息,显示错误信息 -->
      <s:fielderror fieldName= "username"></s:fielderror ><!-- 如果有名字为"username",Field级别错误信息,显示错误信息 -->

    Field在转换错误时,有默认提示,但是可以设定自定义的提示消息。

    在Action所在的包里面添加配置文件:ActionName.properties文件,内部内容如下:
1   invalid.fieldvalue.age= age invalid!

    在转换变量age类型的时候出错就会提示age invalid!

 

  6. 异常处理

    在发生异常的时候,可以制定返回某个页面:

    可以使用全局设定:

1     <global-results>
2         <result name="userInvalid">/404.jsp</result>
3     </global-results>
4     <global-exception-mappings>
5         <exception-mapping result="userInvalid"
6             exception="com.zhangyx.exception.UserInvalidException"></exception-mapping>
7     </global-exception-mappings>

    也可以使用局部设定:

1         <action name="login" class="com.zhangyx.struts.controller.Test" method="execute">
2             <exception-mapping result="userInvalid" exception="com.zhangyx.exception.UserInvalidException" ></exception-mapping>
3             <result name="success">/result.jsp</result>
4        <result name="userInvalid">/userInvalid.jsp</result>
5 </action>

 

  7.Preparable接口

     在struts默认的拦截器中,有一个PrepareInterceptor,这个拦截器将会在继承了Preparable接口的Action中的myExecute执行之前,首先调用prepareMyExecute方法,然后调用prepare方法。这个可以在处理业务之前,做一些准备工作。

 

  8. Servlet API

   有两种方式:

       1. 使用ActionContext,常用的方法有以下几种:这里获得的Map对象与服务器中的Request,session等中的Map对象是同一个。也即可以使用Map对象修改这几个空间中的值。
             ActionContext actionContext = ActionContext.getContext();       //获取ActionContext的实例
             java.util.Map<java.lang.String,java.lang.Object>  getApplication();   //获取Application中存数据的Map
             java.util.Map<java.lang.String,java.lang.Object>  getParameters();    //获取HttpServletRequest中存数据的Map对象
             java.util.Map<java.lang.String,java.lang.Object>  getSession();       //获取HttpSession中存数据的Map对象
           java.lang.String getName();                                             //获取当前的Action的名字。
      2.  使用ServletActionContext,继承自ActionContext,除了继承的上面的几个方法,常用的方法还有以下几种:
              static javax.servlet.http.HttpServletRequest getRequest();              //获取当前的Request对象。 
          static javax.servlet.http.HttpServletResponse getResponse();            //获取当前的Response对象。
 
  9. 拦截器
    拦截器的作用是在执行Action之前或者之后做出一定的处理拦截。
        要实现Struts的拦截器,要做以下的一些步骤:
       1. 建立一个自定义拦截器,实现 Interceptor接口或者是继承AbstractInterceptor类。重写里面的intercept方法,init方法用于初始化,destroy方法用于销毁是处理。
     2. 配置struts.xml。
 1      <interceptors>
 2              <interceptor name="loginInteceptor" class="com.zhangyx.interceptor.LoginInterceptor" ><!-- 自定义拦截器 -->
 3                   <param name="msg" >zhangyx</ param>
 4              </interceptor>
 5              <interceptor-stack name="testInteceptors" >     <!-- 自定义的拦截器栈 -->
 6                   <interceptor-ref name="loginInteceptor" ></interceptor-ref>
 7                   <interceptor-ref name="defaultStack" ></interceptor-ref>     <!-- Struts默认的拦截器栈 -->
 8              </interceptor-stack>
 9      </interceptors>
10      <!-- 将自定义拦截栈testInteceptors栈设置为默认的拦截器栈 -->
11      <default-interceptor-ref name="testInteceptors" ></default-interceptor-ref>

    3. 实现Interceptor接口或者是继承AbstractInterceptor类的拦截器默认拦截所有的方法。如果要仅仅只拦截某一些方法,可以使用MethodFilterInterceptor类,只需要实现doInterceptor方法即可。

    在使用MethodFilterInterceptor的时候,有以下几种情况:

       1)只要includeMethods存在的时候,只对includeMethods中设置的方法拦截。
       2)只有excludeMethods存在的时候,只对不包含在excludeMethods中设置的方法拦截。
       3)都不存在的时候,对所有的方法进行拦截。
 
   
  10. Annotation
     使用Struts的注解的时候,需要确保有convention plugin插件。
     1.修改struts.xml文件:
1    <!-- 设定所有包的父包,默认为convention-default -->
2
<constant name="struts.convention.default.parent.package" value="convention-default" /> 3 <!-- 设定要扫描的包,默认扫描struts、struts2、action、actions等包 --> 4 <constant name="struts.convention.package.locators" value="package1,package2,package3" /> 5 <!-- 设定基础包路径 --> 6 <constant name="struts.convention.package.locators.basePackage" value="com.zhangyx" /> 7 <!-- 设定视图位置,默认为WEB-INF/content --> 8 <constant name="struts.convention.result.path" value="WEB-INF/views" /> 9 <constant name="struts.multipart.maxSize" value="100000000" />

    2. convention plugin查找类的规则:

      1. 实现或继承com.opensymphony.xwork2.Action、ActionSupport的类。

      2. 或者action结尾的类名

    3. url对应规则:

      1. 默认url为 package + "/" + ActionName(去掉Action后缀,切将驼峰命名改为用“-”间隔形式) + ".action"。

      2. 在上面设定的包中设定路径 "/" 。如package1包下的TestAction对应的路径就是"/test.action"。如package1包下的GetIndexAction对应的路径就是"/get-index.action"。

      3. 位于上述包下的子包时,如package1/test包下边的TestAction对应的路径就是"/test/test.action".

    4. 直接访问jsp页面:

      如果没有对应的Action类,将会直接返回对应路径的jsp页面。如访问"test/test.action",将会返回"WEB-INF/views/test/test.jsp";

     5. Annotation
      @ParentPackage    :设定父包,对应配置文件中的package中的"extends"
      @namespace(value)   :指定被修饰的Action所在的命名空间。对应配置文件中的package中的"namespace"
        @Results        :设定全局Results。内含有多个@Result。
      @Result        :设定单个result页面。
      @InterceptorRefs    :设定包的全局过滤器,内含多个@InterceptorRef。
      @InterceptorRef    :设定过滤器
      @ExceptionMappings  :设定全局异常处理,内含多个@ExceptionMapping
      @ExceptionMapping  :设定异常处理页面。
      @Action        :设定Action,对应package中的action。内含value,对应name属性;results,定义多个result;interceptorRefs,定义多个过滤器;exceptionMappings,定义多个异常处理页面。
    
    6. 自动适配方法
      可以通过设定struts.enable.DynamicMethodInvocation,开启DMI,自动匹配"action!method.action"到具体的“method”方法,而不需要设定Action注解。这个值在2.3.20之前默认是true,现在默认为false。
      在struts.xml中添加:
  
1     <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
      或创建struts.properties,在里面设定:
1   struts.enable.DynamicMethodInvocation=true
      还有很多其他的值可以设定,用于各种情况的设定。就不一一列举,可以参考:http://marsvaadin.iteye.com/blog/1543829
 
 
   struts暂时就先这些吧。
      
 
 

posted on 2015-03-29 23:48  墨翟  阅读(192)  评论(0)    收藏  举报

导航