轻量级JavaEE企业应用实战(十八)

详解Struts2的拦截器机制

Struts2拦截器是可插拔式的设计:如果需要使用某个拦截器,只需要在配置文件中应用该拦截器即可;如果不需要,则不需要在配置文件中配置;

拦截器在Struts2中的作用

对于任何MVC框架,他们都会完成一些通用的逻辑控制、例如:解析请求参数、类型转换,将请求参数封装成DTO,执行输入校验,解析文件上传表单中的文件域等;
早期的Struts1把这些动作写在核心控制器里,缺点:
灵活性非常差:强制所有项目都必须使用该框架提供的全部功能,无论是否需要,核心控制器总会完成这些操作
可扩展性很差:如果需要让核心控制器完成更多自定义的处理,需要扩展可信控制器;
Struts2:把大部分核心控制器需要完成的工作按功能分开定义,每个拦截器完成一个功能,这些拦截器自由选择,灵活组合;绝大多数功能是通过这些拦截器来完成的,当StrutsPrepareAndExecuteFilter拦截到用户请求之后,大量拦截器会对请求进行处理,然后才会调用用户开发的Action实例进行处理

Struts2内建的拦截器

这些拦截器配置在struts-default.xml中,如果我们定义的package继承了struts-default包,就可以自由使用这些拦截器,否则需要自行定义;

配置拦截器
<interceptor name="拦截器名" class="拦截器实现类" />

<interceptor name="拦截器名" class="实现类">
    <param name="参数名">参数值</param>
</interceptor>

配置拦截器栈:可配置多个
<interceptor-stack>
    <interceptor-ref name="拦截器名" />
</interceptor-stack>

配置默认拦截器

当配置一个包时,可以配置其指定默认拦截器。一旦某个包指定了默认拦截器,Action中没有显式指定拦截器,则默认拦截器会起作用;如果一旦为包中的Action显式应用了某个拦截器,则默认拦截器失效;如果该Action需要默认拦截器,必须手动添加该拦截器的引用

<package name="包名">
    <interceptors>
        <interceptor .../>
        <interceptor-stack .../>
    </interceptors>
    <default-interceptor-ref name="拦截器名或拦截器栈名" />
    <action .../>
</package>
注:每个包只能定义一个默认拦截器;如果需要多个拦截器共同作为默认拦截器,可以将这些拦截器配置成拦截器栈,然后把该拦截器栈配置成默认拦截器

实现拦截器类

开发自己的拦截器,需要实现com.opensymphony.xwork2.interceptor.Interceptor类

public interceptor Interceptor extends Serializable {
    void destory();
    void init();
    String intercept(ActionInvocation invocation) throws exception;
}

此外,还实现了一个AbstractInterceptor类,已经实现了destory和init方法,所以只需要继承AbstractInterceptor,实现更加简单

public class SimpleInterceptor extends AbstractInterceptor {
    private String name;
    ...
    public String intercept(ActionInvocation invocation) 
        throws Exception {
        LoginAction action = (LoginAction)invocation.getAction();
        long start = System.currentTimeMillis();
        //执行该拦截器的后一个拦截器,如果没有,则执行execute方法
        String result = invocation.invoke();
        long end = System.currentTimeMillis();
    }
}

拦截方法的拦截器

public class MyFilterInterceptor extends MethodFilterInterceptor {
    private String name;
    ...
    public String doInterceptor(ActionInvocation invocation) 
        throws Exception {
        LoginAction action = (LoginAction)invocation.getAction();
        long start = System.currentTimeMillis();
        //执行该拦截器的后一个拦截器,如果没有,则执行execute方法
        String result = invocation.invoke();
        long end = System.currentTimeMillis();
    }
}

重写的是:doInterceptor方法,继承的是MethodFilterInterceptor
原因:MethodFilterInterceptor是AbstractInterceptor的子类,实现了intercept方法,提供了一个doInterceptor抽象方法;可以说已经实现了对Action的拦截行为,但真正的逻辑需要重写doInterceptor来实现;

<interceptors>
    <interceptor name="mysimple" class="com.interceptor.
        MyFilterInterceptor">
        <param name="name">..</param>
    </interceptor>
</interceptors>

<action name="login" class="com.action.LoginAction">
    <result name="error">error.jsp</result>
    ..
    <interceptor-ref name="defaultStack" />
    <interceptor-ref name="mysimple">
        <param name="excludeMethods">execute,test</param>
        <param name="includeMethods">execute</param>
    </interceptor-ref>
</action>

excludeMethods参数指定:execute和test方法不需要被拦截,又通过includeMethods参数指定execute方法需要拦截;
两者冲突,以includeMethods参数指定的为准,即execute被拦截

Struts2中提供了这种过滤的拦截器有几个:
TokenInterceptor
TokenSessionStoreInterceptor
DefaultWorkflowInterceptor
ValidationInterceptor

拦截器执行顺序

在Action的控制方法执行之前,位于拦截器链前边的拦截器将先发生作用,在Action的控制方法执行后,位于拦截器链前边的拦截器后发生作用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章