Struts2 拦截器


拦截器的概念是Servlet过滤器或JDK代理类一样的。拦截器允许横切功能分开实现的动作,以及框架。使用拦截器,可以实现如下:

  • 提供预处理行动之前被称为逻辑。
  • 提供后处理逻辑动作后被调用
  • 捕获异常,这样可以进行替代处理。

Struts2框架提供的许多功能都使用拦截实现的例子包括异常处理,文件上传,生命周期回调和验证等事实上作为Struts2的基础,其功能拦截,这可能有7或8拦截器分配给每个动作。

Struts2框架的拦截器

Struts 2框架提供了良好的箱拦截列表来预先设定的,并准备使用。下面列出了几个重要的拦截:

序号 拦截器 & 描述
1

alias

允许参数在请求中具有不同的名称别名。

2

checkbox

通过为未选中的复选框添加参数值false,帮助管理复选框。

3

conversionError

将字符串转换为参数类型的错误信息放入操作的字段错误中。

4

createSession

如果尚不存在,则自动创建HTTP会话。

5

debugging

为开发人员提供几种不同的调试屏幕。

6

execAndWait

当操作在后台执行时,将用户发送到中间等待页面。

7

exception

将从操作引发的异常映射到结果,允许通过重定向自动进行异常处理。

8

fileUpload

便于文件上传。

9

i18n

在用户会话期间跟踪所选区域设置。

10

logger

通过输出正在执行的操作的名称来提供简单的日志记录。

11

params

设置操作的请求参数。

12

prepare

这通常用于执行预处理工作,例如设置数据库连接。

13

profile

允许记录操作的简单性能分析信息。

14

scope

在会话或应用程序范围中存储和检索操作的状态。

15

ServletConfig

提供对各种基于servlet的信息的访问权限的操作。

16

timer

以动作执行所需的时间的形式提供简单的分析信息。

17

token

检查有效令牌的操作以防止重复表单提交。

18

validation

为操作提供验证支持

请看Struts 2文档的完整细节上面提到的拦截。会告诉如何使用Struts应用程序在一个拦截器。

如何使用拦截器?

让我们来看看如何使用已有的拦截,我们的“Hello World”程序。我们将使用计时器来测量过了多长时间执行操作方法,其目的是拦截。同时使用params拦截器,其目的是发送请求参数的动作。您可以尝试不使用这个拦截您的示例中会发现,没有被设置name属性,因为参数是无法达到动作。

我们将继续HelloWorldAction.javaweb.xmlhelloWorld.jspindex.jsp 文件,因为他们已经建立了范例章节,但让我们如下修改struts.xml文件,添加一个拦截器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name="struts.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <action name="hello"
         class="com.xxkt.struts2.HelloWorldAction"
         method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="timer" />
         <result name="success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

右键点击项目名称,并单击 Export > WAR File 创建一个WAR文件。然后部署在Tomcat 的webapps目录下这个WAR。最后,启动Tomcat服务器和尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。这会给你以下画面:

Struts2拦截器

现在,在给定的文本框中输入单词,并单击Say Hello按钮执行已定义的动作。现在,如果将检查生成的日志,会发现下面的文字:

INFO: Server startup in 3539 ms
27/08/2011 8:40:53 PM
com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
INFO: Executed action [//hello!execute] took 109 ms.

这里底行,正在生成因为这告诉动作发生要执行的总共为 109ms定时器的拦截器。

创建自定义的拦截器

在应用程序中使用自定义的拦截器是一种优雅的方式提供横切的应用功能。创建一个自定义拦截器是很容易的,需要扩展的接口,下面的Interceptor接口:

public interface Interceptor extends Serializable{
   void destroy();
   void init();
   String intercept(ActionInvocation invocation)
   throws Exception;
}

正如其名称所表明的,init()方法提供了一种方法来初始化拦截器,并destroy() 方法提供了一种工具拦截清理。不同的行动,拦截被重用跨请求和需要是线程安全的,尤其是intercept() 方法。

ActionInvocation对象可以访问运行时环境。它允许访问的动作本身和方法调用的动作,并确定动作是否已被调用。

如果不需要初始化或清除代码,可以扩展AbstractInterceptor类。这提供了一个默认的无操作实现的init()destroy()方法。

创建拦截器类

让我们创建Java资源 MyInterceptor.java> src 文件夹:

package com.xxkt.struts2;

import java.util.*;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor {

   public String intercept(ActionInvocation invocation)throws Exception{

      /* let us do some pre-processing */
      String output = "Pre-Processing";
      System.out.println(output);

      /* let us call action or next interceptor */
      String result = invocation.invoke();

      /* let us do some post-processing */
      output = "Post-Processing";
      System.out.println(output);

      return result;
   }
}

就像看到的,实际行动将使用拦截器执行invocation.invoke()调用。所以,可以做一些前处理和一些处理后,根据需要。

该框架本身启动的过程中,在第一次调用ActionInvocation对象的invoke()。每次 invoke()被调用,ActionInvocation的咨询的状态和执行为准拦截接下来。通过请求流以下数据图显示了相同的概念:

Struts2拦截器

创建动作类

让我们创建一个Java文件HelloWorldAction.java的Java下Java Resources > src下面给出的内容包名为 com.xxkt.struts2。

package com.xxkt.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorldAction extends ActionSupport{
   private String name;

   public String execute() throws Exception {
      System.out.println("Inside action....");
      return "success";
   }  

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

在前面的例子中,我们已经看到,这是一个相同的类。我们有标准的“名称”属性的gettersetter方法​​,并返回字符串“success”的执行方法。

创建视图

让我们创建以下JSP文件helloWorld.jsp,在eclipse项目在WebContent文件夹。

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
   Hello World, <s:property value="name"/>
</body>
</html>

创建页面

我们还需要在WebContent文件夹中创建 index.jsp。该文件将作为初始动作URL,用户可以在其中点击告诉Struts 2框架调用 HelloWorldAction类定义的方法呈现 helloWorld.jsp视图

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
   <h1>Hello World From Struts2</h1>
   <form action="hello">
      <label for="name">Please enter your name</label><br/>
      <input type="text" name="name"/>
      <input type="submit" value="Say Hello"/>
   </form>
</body>
</html>

Hello 动作定义在上面的视图文件将被映射到HelloWorldAction类和其执行方法使用struts.xml文件。

配置文件

现在,我们需要注册我们的拦截器,然后调用它默认的拦截器在前面的例子中调用。要注册一个新定义的拦截,直接放在的<interceptors>...</interceptors>标签下<package>的标签插件struts.xml文件。您可以跳过这一步为默认的拦截器,就像我们在我们前面的例子。但在这里,让我们注册和使用它,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name="struts.devMode" value="true" />
   <package name="helloworld" extends="struts-default">

      <interceptors>
         <interceptor name="myinterceptor"
            class="com.xxkt.struts2.MyInterceptor" />
      </interceptors>

      <action name="hello"
         class="com.xxkt.struts2.HelloWorldAction"
         method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="myinterceptor" />
         <result name="success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

应该指出的是,可以注册多个拦截器<package>标签内,同一时间,可以调用多个拦截里面的<action>标签。可以调用相同的拦截器与不同的动作。

web.xml文件需要在 WEB-INF文件夹下创建 WebContent 如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">

   <display-name>Struts 2</display-name>
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

右键点击项目名称,并单击 Export > WAR File 文件创建一个WAR文件。然后部署在Tomcat 的webapps目录下这个WAR。最后,启动Tomcat 服务器和尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp。这会给你以下画面:

struts2拦截器

现在,在给定的文本框中输入任何单词,并单击“Say Hello“ 按钮执行已定义的动作。现在,如果检查生成的日志,会发现下面的文本下方:

Pre-Processing
Inside action....
Post-Processing

多个拦截器

可以想像,配置多个拦截器每个动作很快就会变得非常难以控制。出于这个原因,拦截器与拦截器栈管理。下面是一个例子,直接从在struts-default.xml文件:

<interceptor-stack name="basicStack">
   <interceptor-ref name="exception"/>
   <interceptor-ref name="servlet-config"/>
   <interceptor-ref name="prepare"/>
   <interceptor-ref name="checkbox"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="conversionError"/>
</interceptor-stack>

上面的栈被调用basicStack,可用于在配置中,如下所示。此配置节点放置在<package.../>节点下。每个<interceptor-ref.../>标记引用一个拦截器或拦截器栈已配置在当前的拦截器栈。因此,这是非常重要的,以确保该名称是唯一的所有拦截器和拦截器栈配置配置初始的拦截器和拦截器栈时。

我们已经看到了如何应用拦截的动作,将拦截器栈是没有什么不同。事实上,我们完全使用相同的标签:

<action name="hello" class="com.xxkt.struts2.MyAction">
   <interceptor-ref name="basicStack"/>
   <result>view.jsp</result>
</action>

上述注册的“basicStack”所有6个拦截器完成注册的栈 Hello 动作。应该指出的是,拦截器执行的顺序在配置中。例如,在上述情况下,异常将被执行,servlet 配置等。