开发手册 欢迎您!
软件开发者资料库

Struts 2 - Interceptors

Interceptors在概念上与servlet过滤器或JDKs Proxy类相同.拦截器允许横切功能与动作和框架分开实现

 Interceptors在概念上与servlet过滤器或JDKs Proxy类相同.拦截器允许横切功能与动作和框架分开实现.您可以使用拦截器和减号实现以下功能;

  • 在调用操作之前提供预处理逻辑.

  • 在调用操作后提供后处理逻辑.

  • 捕获异常以便可以执行备用处理.

Struts2 框架中提供的许多功能都是使用拦截器实现的;

示例包括异常处理,文件上传,生命周期回调等.事实上,由于Struts2在拦截器上强调其大部分功能,因此每个动作不可能分配7或8个拦截器.

Struts2框架拦截器

Struts 2框架提供了一个预先配置并准备使用的开箱即用拦截器的良好列表.很少有重要的拦截器列在下面和下面;

Sr.NoInterceptor&说明
1

别名

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

2

复选框

协助通过为未选中的复选框添加参数值false来管理复选框.

3

conversionError

将字符串转换为参数时出现错误信息类型为动作的字段错误.

4

createSession

自动创建HTTP会话(如果尚未存在).

5

调试

为开发者提供了几个不同的调试屏幕.

6

execAndWait

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

7

异常

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

8

fileUpload

便于文件上传.

9

i18n

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

10

记录器

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

11

params

设置操作的请求参数.

12

准备

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

13

个人资料

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

14

范围

在会话或应用范围内存储和检索操作的状态.

15

ServletConfig

提供访问各种基于servlet的信息的操作.

16

计时器

以行为执行所需的时间形式提供简单的分析信息.

17

令牌

Chec ks有效令牌的动作,以防止重复的表格提交.

18

验证

为行动提供验证支持

请查看Struts 2文档,了解有关上述拦截器的完整详细信息.但是我将向您展示如何在Struts应用程序中使用拦截器.

如何使用拦截器?

让我们看看如何使用我们的"Hello World"程序已经存在的拦截器.我们将使用 timer 拦截器,其目的是测量执行操作方法所需的时间.与此同时,我正在使用 params 拦截器,其目的是将请求参数发送给操作.您可以在不使用此拦截器的情况下尝试您的示例,但您会发现 name 属性未设置,因为参数无法访问该操作.

我们将保留HelloWorldAction.java,web.xml,HelloWorld.jsp和index.jsp文件,因为它们已在示例章节中创建,但我们要将 struts.xml 文件修改为添加拦截器如下 :

                                          /HelloWorld.jsp         


右键单击项目名称,然后单击导出> WAR文件以创建War文件.然后在Tomcat的webapps目录中部署此WAR.最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp .这将产生以下屏幕 :

Hello World Struts 4

现在在给定的文本框中输入任何单词,然后单击Say Hello按钮以执行定义的操作.现在,如果您将检查生成的日志,您将找到以下文本 :

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


由于计时器拦截器正在生成底线,这表示操作总共执行了109ms.

创建自定义拦截器

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

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


顾名思义,init()方法提供了一种初始化拦截器的方法,而destroy()方法提供了一种便利用于拦截器清理.与动作不同,拦截器可以跨请求重用,并且需要线程安全,尤其是intercept()方法.

ActionInvocation 对象提供对运行时环境的访问.它允许访问操作本身和方法来调用操作并确定是否已经调用了操作.

如果您不需要初始化或清理代码, AbstractInterceptor 类可以扩展.这提供了init()和destroy()方法的默认nooperation实现.

创建拦截器类

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

package com.it1352.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都会查询其状态并执行下一个拦截器.当调用了所有已配置的拦截器时,invoke()方法将导致操作本身被执行.

下图通过请求流显示相同的概念 :

ActionInvocation

创建动作类

让我们在 Java Resources>下创建一个java文件HelloWorldAction.java. src ,包名为 com.it1352.struts2 ,内容如下.

package com.it1352.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;   }}


这是我们在前面的例子中看到的同一个类.我们有"name"属性的标准getter和setter方法以及返回字符串"success"的execute方法.

创建视图

让我们在你的eclipse项目的WebContent文件夹中创建下面的jsp文件 HelloWorld.jsp .

<%@ page contentType = "text/html; charset = UTF-8" %><%@ taglib prefix = "s" uri = "/struts-tags" %>         Hello World               Hello World,    


创建主页

我们还需要在WebContent中创建 index.jsp 夹.该文件将作为初始操作URL,用户可以单击该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"%>            Hello World               

Hello World From Struts2

               Please enter your name
                           


上面视图文件中定义的 hello 操作将使用struts.xml文件映射到HelloWorldAction类及其execute方法.

配置文件

现在,我们需要注册我们的拦截器,然后调用它,因为我们在前面的例子中调用了默认拦截器.要注册新定义的拦截器,< interceptors> ...标签直接放在< package>下标记 struts.xml 文件.您可以跳过默认拦截器的此步骤,就像我们在前面的示例中所做的那样.但是在这里让我们注册并使用它如下 :

                                                            /HelloWorld.jsp         


应该注意的是,你可以在< package> 标签内注册多个拦截器,同时你可以调用更多< action> 标记内的一个拦截器.您可以使用不同的操作调用相同的拦截器.

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

      Struts 2            index.jsp               struts2               org.apache.struts2.dispatcher.FilterDispatcher                  struts2      /*   


右键单击项目名称,然后单击导出> WAR文件以创建War文件.然后在Tomcat的webapps目录中部署此WAR.最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp .这将产生以下屏幕 :

Hello World Struts 4

现在在给定的文本框中输入任何单词,然后单击Say Hello按钮以执行定义的操作.现在,如果您要检查生成的日志,您将在底部和底部找到以下文本;

Pre-ProcessingInside action....Post-Processing


堆叠多个拦截器

你可以想象,不得不为每个动作配置多个拦截器很快就会变得非常难以管理.因此,拦截器使用拦截器堆栈进行管理.下面是一个示例,直接来自strutsdefault.xml文件 :

                  


以上赌注名为 basicStack ,可以在您的配置中使用,如下所示.此配置节点位于< package .../>下.节点.每个< interceptor-ref .../>标记引用已在当前拦截器堆栈之前配置的拦截器或拦截器堆栈.因此,在配置初始拦截器和拦截器堆栈时,确保名称在所有拦截器和拦截器堆栈配置中是唯一的非常重要.

我们已经看到如何将拦截器应用于操作,应用拦截器堆栈也不例外.事实上,我们使用完全相同的标签 :

      view.jsp


上述"basicStack"注册将通过hello操作注册所有六个拦截器的完整股份.应该注意,拦截器按照已经配置的顺序执行.例如,在上面的例子中,将首先执行异常,第二个将是servlet-config,依此类推.