为什么会有拦截器:
许多Action都需要做一些相同的事情,比如说登录验证,表单输入验证,上传文件时的初始化操作,而有些Action则需要在页面显示前做一些预先填充数据的准备,这些需求在项目中都是很常见的,设想一下,如果在每个action都做一些重复性的功能逻辑,这样实现即繁琐,又违背了软件复用的思想,所以为了解决这个问题,Struts2的设计者们把这些共有的逻辑独立出来,实现成一个个的拦截器,拦截器由此而诞生。
什么是拦截器:
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作,拦截是AOP的一种实现策略。
谈到拦截器,还有一个词需要提一下——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用,访问完之后,拦截器链中的拦截器就会按其之前定义的顺序被逆序调用。
理解拦截器:
拦截器是在某个Action被调用之前与之后执行的,许多框架的核心功能都实现为拦截器,如重复提交,类型转换,校验,文件上传等等,这些实现多亏了拦截器才得以简单实现,每个拦截器都是可插拔的,所以你可以精确为某个需要某种功能的Action配置相应的拦截器。
可以为每个Action配置拦截器,用户自定义的拦截器可以与框架附带的拦截器混合搭配使用,拦截器会在Action执行前做很多繁琐的事情,这样就避免了在每个Action中出现重复代码。
下面是Action的生命周期图:
从图中可以看出Struts2的Interceptor一层一层把Action包裹在最里面,所有的用户请求都会被拦截器所拦截,然后交给Action处理,处理结果以逻辑视图方式返回给用户。而这个调用执行流程,是由Struts 2的配置文件来实现的。可以定义一个拦截器栈为多个拦截器指定执行顺序,在某些时候,拦截器栈中的拦截器的执行顺序是非常重要的。
每个位于堆栈中的Interceptor,除了需要完成它自身的逻辑,还需要完成一个特殊的执行职责。这个执行职责有3种选择:
1) 中止整个执行,直接返回一个字符串作为resultCode
2) 通过递归调用负责调用堆栈中下一个Interceptor的执行
3) 如果在堆栈内已经不存在任何的Interceptor,调用Action
Struts2的拦截器结构的设计,实际上是一个典型的责任链模式的应用。首先将整个执行划分成若干相同类型的元素,每个元素具备不同的逻辑责任,并将他们纳入到一个链式的数据结构中(我们可以把堆栈结构也看作是一个递归的链式结构),而每个元素又有责任负责链式结构中下一个元素的执行调用。
拦截器都是通过代理的方式调用的,当用户请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(List),然后逐个地调用列表中的拦截器,拦截器时序图如下图所示。
从上图中可以看出,拦截器的执行顺序是:
在Action之前,拦截器的执行顺序与堆栈中定义的一致;而在Action和Result之后,拦截器的执行顺序与堆栈中定义的顺序相反。这就好比我们穿衣服一样,早上起床一件一件的套在身上,晚上睡觉前,再一件一件的脱下来。
配置拦截器:
<interceptors> <interceptor name="拦截器名" class="拦截器对应的类" /> <interceptor-stack name="拦截器栈名"> <interceptor-ref name="拦截器名或拦截器栈名1" /> <interceptor-ref name="拦截器名或拦截器栈名2" /> </interceptor-stack> </interceptors>
引用拦截器:
<action name="Action的名称" class="Action对应的类"> <result name="success">视图资源</result> <!-- 使用拦截器,一般配置在result之后, --> <interceptor-ref name="拦截器名或拦截器栈名" /> </action>
此处需要注意的是,如果为Action指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,我们可以在配置文件中手动引入默认拦截器。
<action name="Action的名称" class="Action对应的类"> <result name="success">视图资源</result> <!-- 使用拦截器,一般配置在result之后, --> <interceptor-ref name="defaultStack"/> <interceptor-ref name="拦截器名或拦截器栈名" /> </action>
需要把默认的拦截器放在自定义的拦截器前面,否则会出错。
如果不想为每个Action都配置相同的拦截器或拦截器栈,则可以在配置文件中定义一个默认的拦截器或拦截器栈
<!-- 这句是设置所有Action自动调用的拦截器堆栈 --> <default-interceptor-ref name="拦截器名或拦截器栈名" /> <action name="Action的名称1" class="Action对应的类1" /> <action name="Action的名称2" class="Action对应的类2" />
注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。
自定义拦截器:
自定义一个拦截器需要三步:
1 、自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
2、在strutx.xml中注册上一步中定义的拦截器。
3 、在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。该接口提供了三个方法:
1) void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。
2) void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前,系统将回调该方法。
3) String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。
除此之外,继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor是更简单的一种实现拦截器类的方式,因为此类提供了init()和destroy()方法的空实现,这样我们只需要实现intercept方法。
下面是一个用于验证是否登录的拦截器:
package com.struts.interceptor; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; public class PermissionInterceptor implements Interceptor { private static final long serialVersionUID = -1615930166094288049L; public void destroy() { } public void init() { } public String intercept(ActionInvocation invocation) throws Exception { ActionContext ac = ActionContext.getContext(); Object name = ac.getSession().get("user"); if (name != null) { return invocation.invoke(); // 返回代表视图的字符串,如果还有拦截器则继续执行 } else { return "error"; } } }
简陋的不能在简陋的登陆页面login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>登录页面</title> </head> <body> <% request.getSession().setAttribute("user", "jetty"); %> 用户登录 </body> </html>
如果用户访问过该页面,则在session域中存放键为user,值为jetty的键值对。
下面是配置文件:
<?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="struts" namespace="/test" extends="struts-default"> <interceptors> <!-- 自定义拦截器 --> <interceptor name="permissionInterceptor" class="com.struts.interceptor.PermissionInterceptor" /> <interceptor-stack name="permissionStack"> <!-- 默认的拦截器栈,定义在struts2-core-2.3.8.jar的struts-default.xml中, 因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的, 所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。--> <interceptor-ref name="defaultStack" /> <interceptor-ref name="permissionInterceptor" /> </interceptor-stack> </interceptors> <global-results> <result name="error">/WEB-INF/pages/error.jsp</result> </global-results> <action name="view" class="com.struts.action.ViewInfoAction" method="execute"> <!-- 引用拦截器 --> <interceptor-ref name="permissionStack" /> <result name="success">/WEB-INF/pages/viewinfo.jsp</result> </action> </package> </struts>
简单的Action:
package com.struts.action; public class ViewInfoAction { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String execute() { this.message = "Hello, my name is Jetty"; return "success"; } }
如果用户没有访问过login.jsp,而直接访问名称为view的action,则会跳转到error.jsp
简单的error.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>提示信息页面</title> </head> <body> 您没有权限查看该页面,请登录后查看! </body> </html>
如果用户访问过login.jsp,则用户访问名称为view的action时,会跳转到viewinfo.jsp
简单的viewinfo.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>信息</title> </head> <body> ${message } </body> </html>
即可以在浏览器中看到Hello, my name is Jetty信息。
注:Struts2默认的拦截器栈,定义在struts2-core-2.x.x.jar的struts-default.xml中
相关推荐
本示例将聚焦于如何在Struts2中实现一个自定义拦截器。 首先,我们需要了解拦截器在Struts2中的作用。拦截器是AOP(面向切面编程)的一个核心概念,它允许开发者在动作执行前后插入额外的逻辑,如日志记录、权限...
开发过程中,我们可以根据需要自定义拦截器栈,或者在默认栈基础上添加、替换拦截器。 ### 5. 自定义拦截器 自定义拦截器通常需要实现`Interceptor`接口并覆盖`intercept`方法。在这个方法里,你可以添加自己的业务...
4. **拦截器**:Struts2的拦截器机制允许在Action调用前后执行特定逻辑。JSON插件可能包含用于处理JSON请求和响应的拦截器,比如处理JSON参数的解析和验证。 5. **Action与模型驱动**:如果Action使用模型驱动模式...
在Struts2中,自定义拦截器是实现业务逻辑控制、数据验证、权限管理等功能的重要手段。下面将详细探讨如何在Struts2中实现自定义拦截器来完成权限拦截。 首先,我们需要了解Struts2拦截器的工作原理。拦截器是在...
本文将深入探讨Struts2的内建自定义拦截器及其配置。 首先,让我们理解什么是拦截器。拦截器是基于AOP(面向切面编程)思想的,它们在Action调用前后执行,形成一个拦截器链。每个拦截器都可以执行特定的任务,并且...
使用预定义的拦截器或自定义拦截器来检查和清理输入。 4. **安全编码实践**:遵循安全编码的最佳实践,避免在应用程序中直接使用不受信任的数据。尽量避免使用可能导致代码执行的OGNL表达式,除非已经进行了充分的...
2. **Interceptor**:拦截器是Struts2的一个重要特性,它们是插件式的,可以插入到Action调用流程中,实现如日志、权限检查、事务管理等通用功能。 3. **Result**:结果是Action执行后返回的对象,通常用于渲染视图...
3. **Interceptor(拦截器)**: 拦截器是Struts2的核心特性,它们按照预设的顺序执行,可以在Action执行前后进行额外的操作,如日志记录、权限检查等。 4. **Value Stack**: 用于存储Action实例和其他Action上下文...
Struts2自定义拦截器的配置是Struts2框架中一个非常重要的功能,它允许开发者在Action执行前后插入自定义的逻辑,以实现如权限验证、日志记录、性能监控等多种需求。以下是对标题和描述中涉及的知识点的详细说明: ...
"struts2.chm"可能是Struts2的基础教程,涵盖了框架的基本概念、配置、动作、拦截器等核心组件。在这个文档中,你可以了解到如何设置Struts2的配置文件,如何创建Action类,以及如何使用拦截器进行业务逻辑处理。...
2. **拦截器(Interceptor)**:这是Struts2的一个强大特性,它可以拦截Action调用前后,实现事务管理、日志记录、权限验证等功能。通过配置拦截器栈,开发者可以灵活控制请求处理流程。 3. **OGNL(Object-Graph ...
自定义拦截器是Struts2框架中一个非常重要的特性,允许开发者扩展和定制框架的行为,以满足特定的业务需求。这篇博客文章可能是关于如何在Struts2中创建和使用自定义拦截器的教程。 在Struts2中,拦截器是基于责任...
这里`myStack`是一个拦截器栈,包含`paramsPrepareParamsStack`(Struts2默认的参数处理拦截器栈)和`myCustomInterceptor`(自定义拦截器)。 - **Action配置**:在Action的配置中,通过`<action>`标签的`...
Struts2框架的优势在于其强大的拦截器(Interceptor)机制,允许开发者定义自定义的行为,如日志记录、权限检查等,可以在请求处理流程中的不同阶段插入。此外,它还支持多种结果类型,如Redirect、Stream等,方便...
此外,还包括了Interceptor(拦截器)机制,这是一种AOP(面向切面编程)的实现,允许在Action执行前后插入自定义代码,用于日志记录、权限验证等通用功能。Struts2核心库还支持OGNL(Object-Graph Navigation ...
自定义拦截器是Struts2框架中扩展功能的重要手段,让我们深入探讨如何在Struts2中实现自定义拦截器。 首先,创建一个Web项目是基础步骤,这可以通过IDE如Eclipse或IntelliJ IDEA来完成。确保你的项目包含了Struts2...
1. **自定义拦截器**:Struts2允许开发人员创建自己的拦截器,以扩展或修改请求处理流程。例如,可能有一个拦截器用于处理登录验证,或者用于日志记录和性能监控。 2. **自定义结果类型**:默认的结果类型可能无法...
- **Interceptor(拦截器)**:这些是Struts2中的重要组件,它们在Action调用前后执行,提供了事务控制、日志记录、权限验证等功能。 - **配置文件**:通常有struts.xml或类似的配置文件,用于定义Action、结果...
本篇将深入讲解如何在Struts2中自定义拦截器,并通过提供的源代码进行分析。 拦截器是Struts2框架的核心组件之一,它允许我们在请求到达Action之前或离开Action之后执行一些额外的操作,如日志记录、权限验证、性能...