Struts2拦截器运作

Struts2拦截器运作

拦截器是AOP思想的一种实现,可以将大问题分解成多个小问题。自己做的一个小项目用到struts2的拦截器,那么此处就回顾一下Struts2的拦截器知识。

拦截器(Interceptor)

拦截器是Struts2的核心组件,数据校验(validate,validateX)、国际化、文件上载下载等,这些都靠拦截器。Struts2定义的拦截器是按功能分开的,若要使用某个功能,就在某个控制器(Action)上,或在整个包(struts.xml里的package)里的Action上,加入拦截器。那么与Filter过滤器比起来,这就像插件了。

Filter作用的范围广,针对url过滤。Interceptor则围绕Action和Result。为什么这么说呢?这得看Struts2的工作流程,看图:

Struts2拦截器运作_第1张图片

如图,一个来自浏览器的request,请求Action时,首先会经过多重拦截器,Action执行完,返回Result,Result会原路经过拦截器。

  1. Request发送给StrutsPrepareAndExecuteFilter
  2. StrutsPrepareAndExecuteFilter调用Action映射器ActionMapper,ActionMapper根据请求的URL来查找是否有对应的action可调用。

    若是,返回一个描述了这个action的ActionMapper给StrutsPrepareAndExecuteFilter;

    否,返回null。

  3. 有可用的action,那么StrutsPrepareAndExecuteFilter把请求交给ActionProxy,是开发人员编写的Action的代理类。

  4. ActionProxy创建一个ActionInvocation实例,并进行初始化。
  5. 执行Action前,一系列拦截器就被调用了。

    ActionInvocation持有拦截器、Action实例、结果映射、ActionContext

  6. Action调用结束之后,会根据struts.xml文件中action的result配置对象,得到对应的返回结果。调用execute方法之后,对返回结果进行渲染。
  7. 再次执行拦截器,逆序的。
  8. 结果response返回到浏览器。

使用拦截器

使用拦截器,需要在struts.xml配置,并编写XXXInterceptor类

1.配置拦截器

可以定义一个拦截器:

<interceptor name="permission" class="com.interceptor.AuthorizationInterceptor"/>

若定义时,需要传入参数:

    <interceptor name="permission" class="com.interceptor.AuthorizationInterceptor">
        <param name="param">param</param>
    </interceptor>

定义多个拦截器,则使用拦截器栈,使用拦截器时指定参数的话,会覆盖默认参数:

    <package name="default" extends="rest-default,json-default">
        <interceptors>
            <interceptor name="permission" class="com.interceptor.AuthorizationInterceptor"/>

            <interceptor-stack name="myStack">
                <interceptor-ref name="permission">
                    //使用拦截器时,该包下的action,不拦截以下方法,多个方法,逗号隔开
                    <param name="excludeMethods">valid,logout,index</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        //对整个包下的action执行该拦截,这句别忘了,否则根本就不拦截了 
        <default-interceptor-ref name="myStack" />

        <global-results>
            <result name="error">/WEB-INF/content/error.jsp</result>
        </global-results>
    </package>

2.编写XXXInterceptor类

有三种方式

  • 实现xwork2的Interceptor接口,init(),destory(),intercept()方法
  • 继承AbstractInterceptor类,提供了init(),destory()的空实现,需重写intercept()方法
  • 继承MethodFilterInterceptor类,该类本身也继承了AbstractInterceptor类。不同的是,用该方法编写的拦截器,在struts.xml配置时,可以有excludeMethods,includeMethods两个参数,表示不拦截的方法,和需要拦截的方法。

第二,第三种用得多,以第三种为例,需重写doIntercept()方法

import java.util.Map;

import org.springframework.stereotype.Component;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

public class AuthorizationInterceptor extends MethodFilterInterceptor {

    private static final long serialVersionUID = 1L;

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        ActionContext context = ActionContext.getContext();
        Map<String,Object> session = context.getSession();
        Object user = session.get("user");
        if(user==null) {
            return "login";
        }
        return invocation.invoke();
    }

}

小结

从这次的项目看,当需要自定义拦截器拦截范围时,可以考虑一下分开不同的package,尤其是用struts2的rest plugin时。

拦截器和过滤器很类似,Interceptor在struts.xml配置,拦截action请求,Filter在web.xml配置,拦截一切对象,范围广,更强大。

你可能感兴趣的:(struts2,拦截器,Interceptor,J2EE)