首页 > 代码库 > struts2 之 struts2拦截器

struts2 之 struts2拦截器

1. 拦截器是struts2的核心。Struts2的所有功能都是由拦截器来实现,在struts2中所有功能都是可以自由装配,可插拔实现的。2. 拦截器有点类似于过滤器,只不过拦截器只拦截action。

技术分享

3. 在struts2提供了很多拦截器,分别来实现常见的一些功能。

  • alias:对于HTTP请求包含的参数设置别名。
  • autowiring:将某些JavaBean实例自动绑定到其它Bean对应的属性中,有点类似于Spring的自动绑定。
  • chain:在Web项目开发中,以前使用Struts开发时经常碰到两个Action互相传递参数或属相的情况。该拦截器就是可以让前一个action的参数在现在的action中使用。
  • conversionError:从ActionContext中将转化类型时候发生的错误添加到Action的值域错误中,在校验时候经常被使用到来显示类型转换错误的信息。
  • cookie:从Struts2.0.7版本开始,可以把cookie注入Action中可设置的名字或值中。
  • createSession:自动创建一个HTTP的session,尤其时对需要HTTP的Session的拦截器特别有用。比如下面介绍的TokenInterceptor。
  • debugging:用来对试图间传递的数据进行调试。
  • execAndWait:不显示执行Action,在试图上显示给用户的时一个正在等待的页面,但是Action其实是在“背后”正在执行着。该拦截器尤其在对进度条进行开发的时候特别有用。
  • exception:将异常和Action返回result相映射。
  • fileUpload:支持文件上传的拦截器。
  • i18n:支持国际化的拦截器。
  • logger:拥有日志功能的拦截器。
  • modelDriven:Action执行该拦截器时候,可以将getModel方法得到的result值放入值栈中。
  • scopedModelDriven:执行该拦截器时候,它可以从一个scope范围检索和存储model值,通过调用setModel方法去设置model值。
  • params:将HTTP请求中包含的参数值设置到Action中。
  • prepare:假如Action继承了Preparable接口,则会调用prepare方法。
  • staticParams:对于在struts.xml文件中Action中设置的参数设置到对应的Action中。
  • scope:在session或者application范围中设置Action的状态。
  • servletConfig:该拦截器提供访问包含HttpServletResquest和HttpServletResponse对象的Map的方法。
  • timer:输出Action的执行时间。
  • token:避免重复提交的校验拦截器。
  • tokenSession:和token拦截器类似,但是它还能存储提交数据到session。
  • validation:运行在action-validation.xml文件中定义的校验规则。
  • workflow:在Action中调用validate校验方法。如过Action由错误则返回到input试图。
  • store:执行校验功能时候,该拦截器提供存储和检索Action的所有错误和正确的信息功能。
  • checkbox:试图中如果有checkbox存在的情况,
  • 该拦截器自动将unchecked的checkbox当作一个参数(通常值为“false”)记录下来。这样可以用一个隐藏的表单值来记录所有未提交的checkbox,而且缺省unchecked的checkbox值是布尔类型的,如果视图中checkbox的值设置的不是布尔类型,它就会被覆盖成布尔类型的值。
  • profiling:通过参数来激活或不激活分析检测功能,前提是Web项目是在开发模式下。(涉及到调试和性能检验时使用)
  • roles:进行权限配置的拦截器,如果登录用户拥有相应权限才去执行某一特定Action;

4.在struts2中可以自定义拦截器来实现某些功能。自定义拦截器有两种实现方式,一种是实现Interceptor接口,一种是继承AbstractInterceptor类。

(a)编写一个类,该类实现Interceptor接口:

/**
 * 自定义拦截器  可以实现Interceptor接口也可以继承AbstractInterceptor类
 *
 */
public class MyInterceptor implements Interceptor{
    public void destroy() {
    }
    public void init() {
    }
    /**
     * 返回值为结果名称 :和result的名称匹配 
     */
    public String intercept(ActionInvocation invocation) throws Exception {
        //invoke调用下一个拦截器执行,如果没有拦截器则执行action。如果被拦截,那么直接在该方法中返回运行结果
        System.out.println("执行自定义的拦截器");
        return invocation.invoke();
    }
}

(b)在struts.xml中配置拦截器,拦截器需要配置到package下。

<package name="default" namespace="/" extends="struts-default">
        <!-- 配置拦截器 -->
        <interceptors>
            <!-- 配置自定义拦截器  拦截器的名称要唯一 -->
            <interceptor name="myInterceptor" class="cn.sxt.interceptor.MyInterceptor"></interceptor>
        </interceptors>
        <action name="hello" class="cn.sxt.action.HelloAction" method="hello">
            <result>/success.jsp</result>
            <!-- 引用拦截器 -->
            <interceptor-ref name="myInterceptor"></interceptor-ref>
        </action>
    </package>

(c)在指定action中引用拦截器:

<action name="hello" class="cn.sxt.action.HelloAction" method="hello">
            <result>/success.jsp</result>
            <!-- 引用拦截器 -->
            <interceptor-ref name="myInterceptor"></interceptor-ref>
        </action>

5.拦截器在第一次执行时被创建,以后执行直接用即可。也就是拦截器是singleton。如果使用了自定义的拦截器,那么struts2默认的拦截器将不起作用。需要重新引用。

<action name="hello" class="cn.sxt.action.HelloAction" method="hello">
            <result>/success.jsp</result>
            <!-- 引用拦截器 -->
            <interceptor-ref name="myInterceptor"></interceptor-ref>
            <interceptor-ref name="myTimer"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

6.拦截器栈是拦截器的容器。在一个拦截器栈中可以引用多个拦截器,这样在使用时只需要引用拦截器栈即可,简化了拦截器的引用配置。引用拦截器栈和引用拦截器的方法时一致的。并且一个拦截器可以被多个拦截器栈引用。

<interceptors>
            <!-- 配置自定义拦截器  拦截器的名称要唯一 -->
            <interceptor name="myInterceptor" class="cn.sxt.interceptor.MyInterceptor"></interceptor>
            <interceptor name="myTimer" class="cn.sxt.interceptor.TimerInterceptor"></interceptor>
            <!-- 拦截器栈 -->
            <interceptor-stack name="myStack">
                <interceptor-ref name="myInterceptor"></interceptor-ref>
                <interceptor-ref name="myTimer"></interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <action name="hello" class="cn.sxt.action.HelloAction" method="hello">
            <result>/success.jsp</result>
            <!-- 引用拦截器 -->
            <interceptor-ref name="myStack"></interceptor-ref>
        </action>

7.在之前的action中,并没有引用拦截器,原因时struts2中设置了默认的拦截器。在实际开发中,可以自定义默认拦截器:

<!-- 配置默认拦截器 -->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>
        <action name="hello" class="cn.sxt.action.HelloAction" method="hello">
            <result>/success.jsp</result>
        </action>

8.在应用开发中,有时候可能因为浏览器原因或者是计算机本身的原因导致一组数据多次提交的问题。也是表单重复提交;表单重复提交有两种解决办法,一种是通过js来实现。另一种是结合后台来实现。struts2提供了token拦截器就可以防止表单提交。token拦截器的实现步骤:

(a)在action配置中引用token拦截器:

<action name="add" class="cn.sxt.action.UserAction" method="add">
            <result>/success.jsp</result>
            <result name="invalid.token">/invalid.jsp</result>
            <interceptor-ref name="token"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

(b)配置invalid.token这个结果应该跳转的页面:

<action name="add" class="cn.sxt.action.UserAction" method="add">
            <result>/success.jsp</result>
            <result name="invalid.token">/invalid.jsp</result>
            <interceptor-ref name="token"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

(c)在表单中引用<s:token> 标签:

<form action="add.action" method="post">
        <s:token></s:token>
        name:<input type="text" name="name"/><br>
        age:<input type="text" name="age"/><br>
        <input type="submit" value="http://www.mamicode.com/submit"/>
    </form>

9. 通过拦截器来实现登陆拦截:

/**
 * 登录拦截器
 * 实现 访问资源判断用户是否登录 如果用户登录则继续访问 ,如果用户没有登录则跳转到登录页面
 * @author Administrator
 *
 */
public class LoginInterceptor extends AbstractInterceptor{
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        //获取请求名称
        String actionName = invocation.getProxy().getActionName();
        //如果是登录 则继续执行
        if(actionName.equals("login")){
            return invocation.invoke();
        }
        //如果session存在 则继续执行
        Map<String,Object> session = invocation.getInvocationContext().getSession();
        if(session.get("currentUser")!=null){
            return invocation.invoke();
        }
        //跳转到登录页面
        return Action.LOGIN;
    }
}

10. Action 级别的拦截器会拦截所有action.是一种粗粒度的拦截器。在有的应用中,拦截器可能只拦截部分方法,这种时候应用实现方法拦截器。

public class MethodInterceptor extends MethodFilterInterceptor{

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        System.out.println("方法拦截器被执行");
        return invocation.invoke();
    }
}

配置:

<interceptor-ref name="methodInterceptor">
                    <!-- 配置别拦截的方法 也可以配置不被拦截的方法 -->
                    <param name="includeMethods">add,hello</param>
                </interceptor-ref>

 

struts2 之 struts2拦截器