`
一日一博
  • 浏览: 231076 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Struts2精萃之interceptor

阅读更多
下面这段话能完美诠释拦截器的含义:


拦截器是AOP中的概念,它本身是一段代码,可以通过定义“织入点”,来指定拦截器的代码在“织入点”的前后执行,从而起到拦截的作用。Struts2的Interceptor,其拦截的对象是Action代码,可以定义在Action代码之前或者之后执行拦截器的代码。


这是Struts2.3.4中Interceptor结构图:





图中,我们可以发现,Struts2的Interceptor一层一层,把Action包裹在最里面。这样的结构,大概有以下一些特点:

1. 整个结构就如同一个堆栈,除了Action以外,堆栈中的其他元素是Interceptor

2. Action位于堆栈的底部。由于堆栈"先进后出"的特性,如果我们试图把Action拿出来执行,我们必须首先把位于Action上端的Interceptor拿出来执行。这样,整个执行就形成了一个递归调用

3. 每个位于堆栈中的Interceptor,除了需要完成它自身的逻辑,还需要完成一个特殊的执行职责。这个执行职责有3种选择:
1) 中止整个执行,直接返回一个字符串作为resultCode
2) 通过递归调用负责调用堆栈中下一个Interceptor的执行
3) 如果在堆栈内已经不存在任何的Interceptor,调用Action


一个典型的Interceptor的抽象实现类
public abstract class AroundInterceptor extends AbstractInterceptor {  
        @Override  
        public String intercept(ActionInvocation invocation) throws Exception {  
            String result = null;  
      
            before(invocation);  
            // 调用下一个拦截器,如果拦截器不存在,则执行Action  
            result = invocation.invoke();  
            after(invocation, result);  
      
            return result;  
        }  
          
        public abstract void before(ActionInvocation invocation) throws Exception;  
      
        public abstract void after(ActionInvocation invocation, String resultCode) throws Exception;  
      
    }  


在这个实现类中,实际上已经实现了最简单的拦截器的雏形。或许大家对这样的代码还比较陌生,这没有关系。我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocation中的方法,而ActionInvocation是Action调度者,所以这个方法具备以下2层含义:

1. 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。

2. 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。

所以,我们可以发现,invocation.invoke()这个方法其实是整个拦截器框架的实现核心。基于这样的实现机制,我们还可以得到下面2个非常重要的推论:

1. 如果在拦截器中,我们不使用invocation.invoke()来完成堆栈中下一个元素的调用,而是直接返回一个字符串作为执行结果,那么整个执行将被中止。

2. 我们可以以invocation.invoke()为界,将拦截器中的代码分成2个部分,在invocation.invoke()之前的代码,将会在Action之前被依次执行,而在invocation.invoke()之后的代码,将会在Action之后被逆序执行。

由此,我们就可以通过invocation.invoke()作为Action代码真正的拦截点,从而实现AOP。


Struts2的interceptor工作原理:
从源码中,我们可以看到,Struts2的Action层的4个不同的层次,他们分别是:拦截器(Interceptor)、Action、PreResultListener和Result。每个层次都具备了高度的扩展性和插入点,使得程序员可以在任何喜欢的层次加入自己的实现机制改变Action的行为。

interceptor是由actionInvocation驱动执行的。AroundInterceptor的子类会按照顺序被ActionInvocation调用执行。
intercept()方法对ActionInvocation的invoke()方法进行递归调用,ActionInvocation循环嵌套在intercept()中,一直到语句result = invocation.invoke()执行结束。这样,Interceptor又会按照刚开始执行的逆向顺序依次执行结束。

一个有序链表,通过递归调用,变成了一个堆栈执行过程,将一段有序执行的代码变成了2段执行顺序完全相反的代码过程,从而巧妙地实现了AOP。这也就成为了Struts2的Action层的AOP基础。

interceptor是一个栈结构,先进后出,递归与否与执行顺序无关。

当interceptor1执行调用interceptor2的时候,interceptor1并没有执行完毕,而是被暂时搁置了,因此等到action执行完毕的时候,必然是逆序执行之前被搁置的所有代码。
这是数据结构的知识。



下面是struts2.3.4中struts-default.xml里配置的interceptor:
拦截器名称
功能描述
alias
在不同请求之间将请求参数在不同名字间进行转换,请求内容不变
chain
让前一个Action的属性可以被后一个Action访问,需要和<result type=”chain”>结合使用
checkbox
添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox
cookie
使用配置的name,value来是指cookies
conversionError
将类型转换错误从ActionContext中取出,并转换成Action实例中FieldError错误
createSession
自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务
debugging
提供不同的调试用的页面来展现内部的数据状况。
execAndWait
在后台执行Action,同时将用户带到一个中间的等待页面。
exception
将捕捉到的异常信息输出到指定的异常显示页面
fileUpload
负责解析表单中文件域的内容从而提供文件上传功能
i18n
记录用户选择的locale到session中,从而实现消息资源的国际化
logger
记录日志输出Action的名字
store
存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等
modelDriven
如果一个类实现了ModelDriven,将getModel得到的结果压入ValueStack中
scopedModelDriven
如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部
params
将表单或者HTTP请求中的参数值赋给Action实例中相应的属性
prepare
如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法
scope
将Action状态存入session和application的简单方法
servletConfig
提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问
staticParams
从struts.xml文件中将<action>中的<param>中的内容设置到对应的Action中
roles
确定用户是否具有JAAS指定的Role,否则不予执行
timer
输出Action执行的时间,在做Action性能分析时很有用
token
通过Token来避免双击
tokenSession
和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中
validation
使用action-validation.xml文件中定义的内容校验提交的数据
workflow
调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面
N/A
从参数列表中删除不必要的参数
profiling
通过参数激活profile
multiselect
像复选框checkbox拦截器一样,程序检测到没有值被选中,将没有选中的option的值设定为空的参数


下面是一个登录的interceptor:
package com.chou.jtsms.ui.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;

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

/**
 * @author chou
 * @version 1.0 2012/04/21
 * 拦截除登录以外所有请求判断是否已经登陆过
 * 
 */
public class LoginInterceptor implements Interceptor {

	private static final long serialVersionUID = -3224907200600094135L;

	public void destroy() {

	}

	public void init() {

	}

	/**
	 * 如果是/login.action或者/login请求就跳转到LoginAction处理
	 * 如果不是登录请求就判断是否登陆过,如果登陆成功过还需要再验证一遍,通过namespace来判断该用户应有的权限
	 */
	public String intercept(ActionInvocation invocation) throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpSession session = ServletActionContext.getRequest().getSession();
		String path = request.getServletPath();
		String[] namespaces = StringUtils.split(request.getRequestURI(), "/");
		String namespace = "";
		if (namespaces.length>1) {//截取的namespace应该除去项目名,所以至少数组长度为2
			namespace = namespaces[1];
		}
		if ("/login".equals(path) || "/login.action".equals(path)){
			return invocation.invoke();
		}else {
			UserDTO userDTO = (UserDTO) session.getAttribute("logininfo");
			if(userDTO == null){
				return "noSession";
			}
			if(userDTO.getCansend().equals("1")){//必须有发短信权限
				if(namespace.equals("admin") && userDTO.getKind().equals(UserDTO.ADMIN)){
					return invocation.invoke();
				}
				if(namespace.equals("safeadmin") && userDTO.getKind().equals(UserDTO.SAFE_ADMIN)){
					return invocation.invoke();
				}
				if(namespace.equals("safe") && userDTO.getKind().equals(UserDTO.SAFE_USER)){
					return invocation.invoke();
				}
				if(namespace.equals("common") && userDTO.getKind().equals(UserDTO.COMMON)){
					return invocation.invoke();
				}
			}
		}
		return "noSession";
	}

}


...
<interceptor name="authority" class="com.chou.jtsms.ui.interceptor.LoginInterceptor"/>
<interceptor name="crudLog" class="com.chou.jtsms.ui.interceptor.LogInterceptor" />

<interceptor-stack name="myInterceptor">
     <interceptor-ref name="authority" />
     <interceptor-ref name="paramsPrepareParamsStack" />
     <interceptor-ref name="crudLog" />
</interceptor-stack>

<default-interceptor-ref name="myInterceptor" />
...
  • 大小: 17.1 KB
分享到:
评论

相关推荐

    Struts2 拦截器 Interceptor

    ### Struts2 拦截器 Interceptor #### 一、概述 在Struts2框架中,拦截器(Interceptor)是一种非常重要的机制,它能够帮助开发者实现诸如权限控制、事务管理、日志记录等跨切关注点的功能。通过定义不同的拦截器...

    Struts2拦截器(Interceptor)

    Struts2拦截器(Interceptor) Struts2拦截器(Interceptor)

    struts2 Interceptor详解

    Struts2作为一款流行的Java Web框架,其强大的功能之一就是拦截器(Interceptor)。拦截器在MVC模式中扮演着重要角色,它可以对请求进行预处理和后处理,提供了灵活的扩展机制,使得业务逻辑与表现层更加分离。本文...

    Struts2_interceptor_和_filter区别

    标题和描述均聚焦于“Struts2_interceptor_和_filter区别”,这暗示着对比和解析Struts2框架中拦截器(Interceptor)与过滤器(Filter)的差异是本文的核心议题。接下来,我们将深入探讨这两者在功能、实现方式以及...

    struts2 Interceptor拦截器

    Struts2框架的核心设计理念之一是MVC(Model-View-Controller),它将业务逻辑、数据和界面分离,使得应用程序更加清晰、易于维护。在Struts2框架中,**Interceptor(拦截器)**是一个关键组件,它允许开发者在特定...

    struts2 interceptor介绍

    ### Struts2 Interceptor深入解析 #### 一、Interceptor概览与核心机制 在Struts2框架中,Interceptor(拦截器)扮演着极其关键的角色,它不仅能够增强框架的灵活性,还能提供一系列强大的功能,包括但不限于权限...

    STRUTS2:拦截器Interceptor

    STRUTS2:拦截器Interceptor

    struts2 拦截器interceptor教程 示例源码

    struts2 拦截器_教程.zip

    Struts2.x_Interceptor

    Interceptor(拦截器)是Struts2框架的核心组件之一,它在Action调用前后执行,实现了业务逻辑的分离,增强了代码的复用性和灵活性。 Interceptor是Struts2实现AOP(面向切面编程)的一种方式,主要负责处理请求和...

    struts2 interceptor annotation plugin

    在Struts2中,拦截器(Interceptor)是核心组件之一,它们在Action执行前后进行拦截,实现了如日志记录、权限检查、数据验证等业务逻辑。而"struts2 interceptor annotation plugin"则是Struts2框架提供的一种使用...

    struts2项目开发

    Struts2 框架的主要组件包括 Action、Interceptor、Result、View 等。Action 负责处理用户的请求,Interceptor 负责拦截和处理请求,Result 负责处理请求的结果,View 负责将处理结果显示给用户。 Struts2 项目开发...

    saif(struts1 interceptor)

    然而,在Struts1的原生设计中,并没有内置拦截器(Interceptor)这一概念,这与后来的Struts2框架有所不同。Struts2引入了拦截器,极大地增强了框架的灵活性和可扩展性。但是,由于Struts1的流行和项目需求,"saif...

    Struts2接口文档

    Struts2的核心组件包括Action、Result、Interceptor(拦截器)等,这些组件通过特定的接口进行交互。Action接口定义了处理用户请求的方法,如execute(),开发者通常会自定义Action类来实现业务逻辑。Result接口则...

    struts2jar包

    1. **struts2-core.jar**:这是Struts2的核心库,包含了框架的主要组件,如Action、Result、Interceptor等。它定义了请求处理的流程,提供了ActionContext、ValueStack等关键对象。 2. **xwork-core.jar**:XWork是...

    留言板留言板struts2留言板struts2

    3. **拦截器(Interceptor)**:Struts2的核心组件之一,可以理解为对请求和响应进行预处理和后处理的中间层。拦截器链是Struts2的一大特色,允许开发者自定义拦截器,实现如权限验证、日志记录、事务管理等功能。 4....

    struts2 拦截器写法

    Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.

    Struts2.3.6实现自定义拦截器Interceptor

    &lt;interceptor name="mMethodInterceptor" class="com.win.struts2.interceptor.test.MMethodInterceptor"&gt;&lt;/interceptor&gt; &lt;!-- ... --&gt; ``` 总结来说,自定义拦截器是Struts2框架中增强功能和控制流程的重要手段...

    struts2jar.zip

    1. **Struts2核心库**:struts2-core.jar,包含了框架的核心功能,如Action、Result、Interceptor等。 2. **插件包**:根据项目需求,可能需要其他的插件,如struts2-convention-plugin.jar(用于自动配置)、...

    struts2小程序 struts2代码

    Struts2是一个强大的Java web应用程序框架,用于构建和管理MVC(模型-视图-控制器)架构的应用。这个“struts2小程序”很可能是开发者利用Struts2框架开发的一个小型项目,可能包含了基本的CRUD操作或其他特定功能。...

    struts2的各种jar包

    2. **核心库**:`struts2-core.jar`是框架的核心,包含Action、Result、Interceptor、Freemarker模板引擎等相关类,它是Struts2运行的基石。 3. **拦截器库**:`struts2-convention-plugin.jar`和`struts2-...

Global site tag (gtag.js) - Google Analytics