Struts2 Interceptor

Interceptors allow you to define code to be executed before and/or after the execution of an Action method. (The "Filter" pattern.)


downpour在这里对拦截器做了很好的描述
http://struts2.group.iteye.com/group/wiki/1397-deep-into-struts2-interceptors



Struts2 Interceptor_第1张图片
从下载的struts2的document中截取的一副ActionLifeCyle中可以看到拦截器的设计是一个典型的责任链模式。



定义我们自己的拦截器可以通过实现Interceptor接口或extends AbstractInterceptor抽象类
Interceptor接口

public interface Interceptor extends Serializable {

     void destroy();

     void init();

     String intercept(ActionInvocation invocation) throws Exception;

} 


该接口和Servlet规范中Filter的定义大同小异,Intercept()方法是我们实现拦截机制的核心方法,这个方法通过传递一个ActionInvocation的实例达到递归调用的目的,ActionInvocation是后续流程的核心调度者。

该接口提供了一个抽象的实现类AbstractInterceptor,该类提供了destory()和init()的空实现
public abstract class AbstractInterceptor implements Interceptor {

    public void init() {
    }
    
    public void destroy() {
    }

    /**
     * Override to handle interception
     */
    public abstract String intercept(ActionInvocation invocation) throws Exception;
}
在拦截器中通过传递ActionInvocation实例,调用其invoke()方法来达到流程继续往下执行,这里我们可以直接在拦截器中返回一个resultCode,如果我们不使用invocation.invoke()来完成堆栈中下一个元素的调用,而是直接返回一个字符串作为执行结果,那么整个执行将被中止。如:
public class SecurityInterceptor extends AbstractInterceptor {

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		
		if(LoginAction.class == invocation.getAction().getClass()) {
			return invocation.invoke();
		}
                  return "";
	}

}
也可以通过invoke()方法使流程继续向下执行
public class LoginInterceptor extends AbstractInterceptor {

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		String username = request.getParameter("username");
		String password = request.getParameter("password");  System.out.println("LoginInterceptor invocation.invoke()之前的代码.....");
		//invocation.invoke();之前的代码会在Action之前执行

		String result = invocation.invoke();
		
		//invocation.invoke();之后的代码会在Action之后执行
		System.out.println("LoginInterceptor invocation.invoke()之后的代码.....");
		return result;
	}
}
如果有下一个过滤器就调用下一个过滤器,没有就通过invokeActionOnly()调用Action

ActionInvocation.invoke()之前的代码将会在Action被调用之前被执行,invocation.invoke()之后的代码将会在Action被调用之后逆序执行

拦截器拦截的类型分为:Before(到达Action之前)、After(Action之后)、PreResultListener(Action has been executed but before the Result is executed).
Struts2 Interceptor_第2张图片
Struts2 Interceptor_第3张图片

Struts2自带了一系列拦截器,我们可以参考struts2-core-x.x.x.jar包下面的struts-default.xml,里面定义了一系列的系统自带的拦截器(<interceptor>指定)、拦截器栈(<interceptor-stack>),及默认的拦截器(<default-interceptor-ref name="defaultStack"/>),这也是我们配置Action时要extends="struts-default"的原因,这些拦截器做了很多前期的准备和初始化工作,可以看出Interceptor结构实在是Struts2/Xwork设计中的精华所在,当我们配置的Action自定义了拦截器的时候,默认的defaultStack便不起作用了,这时要手动加上

前面说到ActionInvocation是struts2核心的真正调度者,Debug其源代码发现这一切操作都是在其实现类DefaultActionInvocation中实现的。
其核心代码,如果存在下一个拦截器:
//得到下一个拦截器,传递invocation参数,调用其intercept()方法,
//而intercept中又调用invoke(),以此递归实现
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);

没有后续拦截器存在调用Action
resultCode = invokeActionOnly();
这是配置了PreResultListener的调用代码:
listener.beforeResult(this, resultCode);
最后执行Result:
// now execute the result, if we're supposed to
if (proxy.getExecuteResult()) {
      executeResult();
}
在配置拦截器的时候还可以指定<param>参数(使用部分的参数配置会覆盖定义部分的参数配置
),在拦截器中获取配置的参数要提供一个相应的属性并提供setter/getter方法

你可能感兴趣的:(struts2,Interceptor)