struts2的工作流程

用户请求
       ——>    StrutsPrepareAndExecuteFilter
       ——>    Interceptor
       ——>    Action
       ——>    Result
       ——> Jsp/html
       ——> 响应

Struts2拦截器

拦截器(interceptor)是Struts2最强大的特性之一,拦截器可以让你在Action和result被执行之前或之后进行一些处理。同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很多特性都是由拦截器来完成的。例如params拦截器将HTTP请求中的参数解析出来,并设置为Action的属性。servlet-config拦截器直接将HTTP请求中的HttpServletRequest对象化HttpServletResponse对象传给Action。

Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特性。这些内置的拦截器在struts-default.xml中配置。只有配置了拦截器,拦截器才可以正常的工作和运行。在struts-default.xml中拦截器的配置片段为:


        
        //…其他拦截器配置
        
              
                
                
                //…其他拦截器的引用
             
    
    
① package将属性abstract设置为true,代表此package为一个抽象的package。抽象package和非抽象package的区别在于抽象的package中不能配置action。
② name属性指定拦截器的名字,class属性指定拦截器的完全限定名。
③ 多个拦截器可以组成拦截器栈。name属性为拦截器栈的名字。
④ 指定当前package的默认拦截器(栈)。当前指定的默认拦截器栈为defaultStack,该拦截器栈是Struts2运行的一个基本拦截器栈,一般我们不用在自己配置它,因为在大多数情况下,我们自定义的package是继承自struts-default这个package的。


我们以Struts2内置的timer拦截器为例,来学习如何在我们的应用中添加其他的拦截器。timer拦截器可以统计action执行的时间。我们可以修改package中默认的拦截器,那么将替换掉struts-default中配置的defaultStack拦截器栈,导致Struts2无法正常运行,比如无法获取表单的值等等。那么该如何正确的配置呢?可以在添加新的拦截器的基础上加入defaultStack拦截器栈,这样就可以保证defaultStack拦截器栈的存在。


    
         
             
        
    
    
        suc.jsp
        index.jsp
        err.jsp
    

① 添加一个自定义的拦截器栈,并在其中包含time拦截器和defaultStack拦截器栈。
② 设置当前的package的默认拦截器栈为自定义的拦截器栈。

修改package的默认拦截器会应用的package中的所有Action中,如果只想给其中一个Action添加拦截器,则可以这样来做:


    
        
            
            
        
    
    
        suc.jsp
        index.jsp
        err.jsp
    

                                                               
① 给UserAction添加拦截器。

如果要创建自己的拦截器,只需要实现Interceptor接口,该接口中定义了以下三个方法:

void init():

在拦截器初始化之后,在执行拦截之前,系统调用该方法。对于一个拦截器而言,init方法只会被调用一次。

String intercept(ActionInvocation invocation) throws Exception:

该方法是拦截器的拦截方法,返回一个字符串,系统将会跳转到该字符串对应的视图资源。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该对象的invoke方法,将控制权转给下一个拦截器或者转给Action的execute方法。

void destroy():

该方法与init方法对应,在拦截器示例被销毁之前,系统将会调用该方法。

除了Interceptor接口外,Struts2中还提供了一个AbStractInterceptor类,该类提供了一个init和destroy方法的空实现。如果不需要就不用重写这两个方法,可见继承自AbstractInterceptor类可以让我们构建拦截器时变得简单。

下面我们构建自己的拦截器,实现timer拦截器的效果。

public class MyInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        long startTime = System.currentTimeMillis();  ①
        String result = invocation.invoke();  ②
        long endTime = System.currentTimeMillis();  ③
        System.out.println("Action执行共需要" + (endTime - startTime) + "毫秒");
        return result;
    }
}
① 获得Action执行的开始时间。
② 将控制权交给下一个拦截器,如果该拦截器是最后一个拦截器,则调用Action的execute方法。
③ 获得Action执行的结束时间。

在配置文件struts.xml中配置拦截器:


    
        
            
        
    
    
        
        suc.jsp
        index.jsp
        err.jsp
    

                                                    
① 定义一个新的拦截器,name属性为拦截器的名字,class属性为拦截器的完全限定名。
② 在拦截器栈中加入新的拦截器。

从拦截器的运行原理上和我们以前学习的Servlet中的过滤器是不是很相像呢?其实它们只有一个重要的区别,就是拦截器的工作是不依赖容器的,这会在进行单元测试时变得简单。



struts2.0中struts.xml配置文件详解



    
    
                                             
                                             
    
    
        
            
            
            
            
            
                
                
            
        
                                                 
        
        
                                                 
                                                 
        
        
            /error.jsp
        
                                                 
        
        
            
            
                                                 
            
         /talk.jsp
         
         http://www.sina.com