Struts2拦截器

 

一、内容提要

1.拦截器的概念及应用

2.STRUTS2自带的拦截器

3.自定义拦截器

4.自定义拦截器的应用

二、拦截器的概念及应用

拦截器(Interceptor)是Struts2的一个重要特性。Struts2框架的大多数核心功能都是通过拦截器来实现的,像避免表单重复提交、类型转换、对象组装、验证、文件上传等,都是在拦截器的帮助下实现的。拦截器之所以称为“拦截器”,是因为它可以在Action执行之前或执行之后拦截调用。

Struts2将它的核心功能放到拦截器中实现而不是分散到Action中实现,有利于系统的解耦,使得功能的实现类类似于个人电脑的组装,变成了可插拔的。需要某个功能就“插入”一个拦截器,不需要某个功能就“拔出”。

拦截器应用:

  • 为action动态添加输入验证
  • 对象组装(也就是进行数据类型转换)
  • 权限控制
  • 日志记录等

三、STRUTS2自带的拦截器

Struts2本身提供了很多的拦截器,这些拦截器已经在struts-default.xml文件中定义,在Web应用程序中可以直接引用这些拦截器。这也是为什么struts配置文件里经常有这样一个属性extends="struts-default"加载Struts2本身提供的拦截器。

具体情况如下:

序号

拦截器名称

作用

1

alias

在请求之间转换名字不同的相似参数

2

chain

将所有的属性从前一个Aciotn复到当前Action中

3

params

最基本的一个拦截器,负责解析HTTP请求中的参数,并将参数值设置成Action对应的属性值

4

cookie

基于cookie的名/值设置Action的属性

5

conversionError

将类型转换错误从ActionContext中取出,添加到Action字段错误中

6

createSession

自动创建一个HttpSession对象

7

debugging

当struts.devMode属性设置为true,才有,用于调试

8

execAndWait

可以用于防止后台Action Http请求超时

9

exception

提供了异常处理的核心功能

10

fileUpload

用于对文件上传提供支持

11

i18n

用于支持国际化

12

timer

负责输出action的执行时间,用于分析action

13

token

检查传到Action的token值的有效性,防表单重复提交

四、自定义拦截器

作为“框架(framework)”,可扩展性是不可或缺的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。

在Struts2中编写拦截类,有如下二种方式:

实现Interceptor此接口

继承AbstractInterceptor类(一般会选择此种方式)

案例:

编写拦截器类:

注意:在编写拦截器时要注意,拦截器必顺是无状态的,换句话 说,在拦截器类中不应该有实例变量。这是因为struts2对每一个Action的请求使用的是同一个拦截器实例来处理,如果拦截器有状态,在多线程并发情况下,拦截器的状态将不可预测。

package com.silvan.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class AroundInterceptor extends AbstractInterceptor {
         public void init() {
                   System.out.println("这是一个初始化方法");
         }
         public String intercept(ActionInvocation invocation) throws Exception {
                   String result = "";
                   System.out.println("我是在action的execute方法执行之前动作");
                   result = invocation.invoke();
                   System.out.println("我是在action的execute方法执行之后动作");
                  return result;
         }
         public void destroy() {
                   System.out.println("这是一个清理方法");
         }
}

Struts.xml配置拦截器

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
   <package name="InterceptorDemo" extends="struts-default">
       <!--在这里定义拦截器 -->
       <interceptors>
           <interceptor name="around" class="com.silvan.interceptor.AroundInterceptor" />
       </interceptors>
       <action name="interceptor" class="com.silvan.action.InterceptorAction">
           <result>/index.jsp </result>
  <!--在这里使用拦截器,当使用自定义的拦截器后,默认的拦截器将失效,这样原本struts提供的拦截器功能就会失效,比如用于类型转换的params拦截器 -->
           <interceptor-ref name="around"/>
       </action>
    </package>
</struts>

Action类

public class InterceptorAction extends ActionSupport {

   private int id;

   private String userName;

   @Override

   public String execute() throws Exception {

      System.out.println("执行interceptor Action……");

      return SUCCESS;

   }

//Get/set……

}

页面显示Login

<form action="interceptor">

        <table>

           <tr><td>编号:<input type="text" name="id" value="1"></td></tr>

           <tr><td>姓名:<input type="text" name="userName" value="ross"></td></tr>

           <tr><td><input type="submit" value="submit"></td></tr>

        </table>

</form>

返回显示index

<body>

    编号:<s:property value="id"/><br/>

    用户名:<s:property value="userName"/>

  </body>

当自定义了拦截器后,默认的拦截器将失效, index页面取不到登录的值,所以需要引入默认的拦截器。配置如下:

Struts.xml配置拦截器

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="InterceptorDemo" extends="struts-default">

       <!--在这里定义拦截器 -->

       <interceptors>

           <interceptor name="around" class="com.silvan.interceptor.AroundInterceptor" />

                     <!-- 定义拦截器栈 -->

           <interceptor-stack name="myStack">

              <!--引用拦截器  -->

              <interceptor-ref name="around"></interceptor-ref>

              <!-- 引入默认的拦截器 -->

              <interceptor-ref name="defaultStack"></interceptor-ref>

           </interceptor-stack>

       </interceptors>

<!—针对包引用拦截器,这样就不仅仅对某个action起作用 -->

<!--       <default-interceptor-ref name="mystack"/> -->

       <action name="interceptor" class="com.silvan.action.InterceptorAction">

           <result>/index.jsp </result>

            <!—引用拦截器栈 -->

           <interceptor-ref name="myStack"/>

       </action>

    </package>

</struts>

Struts.xml配置多个拦截器方式:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="InterceptorDemo" extends="struts-default">

       <!--在这里定义拦截器 -->

       <interceptors>

           <interceptor name="around" class="com.silvan.interceptor.AroundInterceptor" />

           <interceptor name="around1" class="com.silvan.interceptor.AroundInterceptor1" />

           <!-- 定义拦截器栈 -->

           <interceptor-stack name="myStack">

              <!--引用拦截器  -->

              <interceptor-ref name="around"></interceptor-ref>

              <interceptor-ref name="around1"></interceptor-ref>

              <!-- 引入默认的拦截器 -->

              <interceptor-ref name="defaultStack"></interceptor-ref>

           </interceptor-stack>

       </interceptors>

<!--       <default-interceptor-ref name="mystack"/> -->

       <action name="interceptor" class="com.silvan.action.InterceptorAction">

           <result>/index.jsp </result>

           <interceptor-ref name="myStack"/>

       </action>

    </package>

</struts>

五、练习

需求分析

在一个系统中,如果用户没有选择登录系统就直接使用相应的资源,从常理上来讲这是不允许的。也就是说在当用户访问受保护资源时,拦截器截获用户请求,判断用户是否已经登录,如果没有登录,则向用户显示登录页面,请求用户登录如果用户已经登录,则向用户显示资源。

Action   

public String execute() throws Exception {

      System.out.println("执行interceptor Action……");

      if(userName!=null){

         ActionContext context = ActionContext.getContext();

         Map<String,Object> session = context.getSession();

         session.put("userName", userName);

      }

      return SUCCESS;

   }

Interceptor

public String intercept(ActionInvocation invocation) throws Exception {

      String result = "";

      System.out.println("我是在action的execute方法执行之前动作");

      String user =(String) ActionContext.getContext().getSession().get("userName");

      if(user!=null && "".equals(user)){

         System.out.println("非法访问……");

         return "error_login";

      }

      result = invocation.invoke();

      System.out.println("我是在action的execute方法执行之后动作");

      return result;

   }

配置

<!--     <global-results name="error_login">/login.jsp</global-results> -->

<!--     <default-interceptor-ref name="mystack"/> -->

      <action name="interceptor" class="com.silvan.action.InterceptorAction">

         <result>/index.jsp </result>

         <result name="error_login">/login.jsp</result>

         <interceptor-ref name="myStack"/>

      </action>

思考:过滤器和拦截器的区别?

原文地址:https://www.cnblogs.com/zhouyeqin/p/7172930.html