Java EE框架开发技术与案例教程
上QQ阅读APP看书,第一时间看更新

4.4 Struts 2的拦截器

拦截器(Interceptor)是Struts 2的核心组成部分。拦截器动态拦截Action调用的对象,它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者之后运行,也可以在一个Action执行之前阻止Action执行。拦截器分为两类:Struts 2提供的内建拦截器和用户自定义的拦截器。

对于Struts 2框架提供的内建的拦截器,可以完成框架所提供的相关功能和操作,例如,文件的上传和下载、国际化、转换器和数据校验等。对于Struts 2内建拦截器的应用将在4.5~4.7节给出。本节主要介绍Struts 2拦截器的自定义实现。

4.4.1 Struts 2拦截器的自定义实现

为了实现自定义拦截器,Struts 2提供了Interceptor接口,以及对该接口实现的一个抽象拦截器类(AbstractInterceptor)。创建拦截器类可以实现Interceptor接口,也可以直接继承AbstractInterceptor类;同时,Struts 2还提供了一个MethodFilterIntercepter类,该类是AbstractInterceptor类的子类,若要实现方法过滤,就需要继承MethodFilterIntercepter,设计方法拦截器。

1.拦截器接口与抽象拦截器类

Struts 2提供的Interceptor接口(Interceptor.java)的代码如下。

    import com.opensymphony.xwork2.ActionInvocation;
    import java.io.Serializable;
    public interface Interceptor extends Serializable {
        void destroy(); //用于在拦截器执行完之后,释放init()方法里打开的资源
        void init(); //由拦截器在执行之前调用,主要用于初始化系统资源
        String intercept(ActionInvocation invocation) throws Exception;
    }

其中,String intercept(ActionInvocation invocation) throws Exception是拦截器的核心方法,用于实现具体的拦截操作,返回一个字符串作为逻辑视图。

另外,抽象拦截器类(AbstractInterceptor),是对接口Interceptor的一种实现。

2.自定义拦截器

用户自定义拦截器,首先通过实现Interceptor接口(或继承AbstractInterceptor或继承MethodFilterIntercepter)的类创建自定义拦截器类;然后,在struts.xml中注册自定义的拦截器;最后,在需要使用的Action中引用已经注册的拦截器。

(1)创建拦截器类

实现接口Intercepter(或继承AbstractInterceptor),并在interceptor方法中加入有关的处理代码,其格式示例如下。

(2)在Struts.xml中注册拦截器并引用拦截器

在struts.xml中注册声明拦截器,并在Action中引用拦截器,配置格式如下。

注意:一旦某个Action引用了自定义的拦截器,Struts 2默认的拦截器就不会再起作用了,为此,还需要引用默认拦截器栈。

3.自定义方法拦截器

Struts 2还提供了方法拦截器类MethodFilterInterceptor,该类继承AbstractInterceptor类,重写了intercept()方法,并提供了新的抽象方法doInterceptor()。通过该拦截器可以指定哪些方法需要被拦截,哪些方法不需要被拦截。其创建过程如下。

1)建立拦截器:继承MethodFilterInterceptor,创建一个拦截器。

2)在配置文件内注册拦截器:该类拦截器只能配置在Action内部,格式如下。

注意:

(1)exculdMethods:指定不被拦截的方法,若有多个方法以逗号分隔。

(2)includMethods:指定被拦截的方法,若有多个方法以逗号分隔。

4.在interceptor方法中,利用参数ActionInvocation可获取页面提交的信息

4.4.2 案例——文字过滤器的设计与应用

例4-6】开发一个网上论坛过滤系统,如果网友发表的文字中有不文明的文字,将通过拦截器对不文明的文字进行自动替代。该示例只是给出了一种简单的过滤,过滤是否有“讨厌”文字,若有“讨厌”,则用“喜欢”代替要过滤的“讨厌”,形成新的文本内容并显示在论坛上。运行界面如图4-6所示。

图4-6 【例4-6】的运行界面

a) 提交页面b) 过滤后显示信息的页面

【分析】对于该案例,需要编写一个自定义拦截器(MyInterceptor.java),一个发表新闻评论的页面(news.jsp)及其对应的业务控制器PublicAction类,以及评论成功页面success.jsp。

【设计关键】该问题的关键是设计一个拦截器MyInterceptor.java,该拦截器的工作过程是:在页面提交后,获取所提交的请求参数信息,判定其是否含有“讨厌”文字,并进行处理,处理后重新修改请求参数值,然后再执行Action或下一个过滤器。

【实现】

1)建立工程:struts2_Interceptor,并在web.xml中配置核心控制器。

2)根据如图4-6所示的页面,设计评论页面(news.jsp),其代码如下。

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <html> <head> <title>评论</title> </head>
        <body>
          请发表你的评论!<hr>
          <s:form action="public" method="post">
                <s:textfield name="title" label="评论标题" maxLength="36"/>
                <s:textarea name="content" cols="36" rows="6" label="评论内容"/>
                <s:submit value="提交"/>
        </s:form>
        </body>
    </html>

3)编写评论成功页面(success.jsp)。

    <%@ page contentType="text/html; charset=UTF-8" %>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <html> <head> <title>评论成功</title> </head>
        <body>
          评论如下:<hr>
          评论标题:<s:property value="title"/> <br>
          评论内容:<s:property value="content"/>
      </body>
    </html>

4)评论页面对应的业务控制器(PublicAction.java)。

    package  action;
    import com.opensymphony.xwork2.ActionSupport;
    public class PublicAction extends ActionSupport{
        private String title;
        private String content;
        //属性的getter/setter方法
        public String execute(){return SUCCESS; }
    }

5)编写自定义拦截器:MyInterceptor.java。

编写一个自定义拦截器用于对发表评论的内容进行过滤,代码如下。

    package interceptor;
    //省略了import;
    public class MyInterceptor extends AbstractInterceptor {
        public String intercept(ActionInvocation ai) throws Exception {
          //获取页面提交的所有属性及属性值
          Map<String, Object> parameters = ai.getInvocationContext().getParameters();
          //对每对属性、属性值分别进行过滤,将过滤后的内容再保存到该属性中
          for (String key : parameters.keySet()) {
            Object value = parameters.get(key);
            if ( value ! = null && value instanceof String[]) {
                String[] valueArray = (String[]) value;
                for (int i = 0; i < valueArray.length; i++) {
                  if( valueArray[i] ! = null ){
                    //判断用户提交的评论内容是否有要过滤的内容
                    if(valueArray[i].contains("讨厌")) {
                        //以“喜欢”代替要过滤的内容“讨厌”
                        valueArray[i] =valueArray[i].replaceAll("讨厌", "喜欢");
                        //把替代后的评论内容设置为Action的评论内容
                        parameters.put(key, valueArray);
                    }
                  }
                }
              }
          }
         return ai.invoke(); //执行下一个拦截器或Action
      }
    }

6)在struts.xml中配置自定义拦截器和Action。

修改配置文件struts.xml,在配置文件中配置拦截器和Action。

    <struts>
        <package name="default" namespace="/" extends="struts-default">
          <interceptors>
                <! --文字过滤拦截器配置,replace是拦截器的名称-->
              <interceptor name="replace" class="interceptor.MyInterceptor" />
          </interceptors>
        <action name="public" class="action.PublicAction"><! --文字过滤Action配置-->
              <result name="success">/success.jsp</result>
              <result name="login">/success.jsp</result>
                <interceptor-ref name="replace"/>  <! --使用自定义拦截器-->
                <interceptor-ref name="defaultStack"/>  <! --Struts 2系统默认拦截器-->
          </action>
        </package>
    </struts>

7)项目部署和运行。部署后,运行效果如图4-6所示。