您的位置:首页 > 编程语言 > Java开发

Struts2拦截器实现原理的理解

2012-09-06 16:30 495 查看
一.Struts2(MVC框架)

原理图:


二.Struts2拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。我们可以从上面的原理图中看出,Struts2拦截器在Action前执行和返回result后的操作,流程是:Interceptor1
2 3  Action Result(返回) Interceptor 3 2 1(逆序执行一遍)

再来看看Struts2的拦截器执行源码:

(DefaultActionInvocation.java)

public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
UtilTimerStack.push(profileKey);

if (executed) {
throw new IllegalStateException("Action has already executed");
}
//拦截器栈的执行
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
//执行Interceptor拦截器里的intercept(ActionInvocation invocation)
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
//拦截器栈没有拦截器,则直接执行Action
resultCode = invokeActionOnly();
}

// this is needed because the result will be executed, then control will return to the Interceptor, which will
// return above and flow through again
if (!executed) {
if (preResultListeners != null) {
for (Object preResultListener : preResultListeners) {
PreResultListener listener = (PreResultListener) preResultListener;

String _profileKey = "preResultListener: ";
try {
UtilTimerStack.push(_profileKey);
listener.beforeResult(this, resultCode);
}
finally {
UtilTimerStack.pop(_profileKey);
}
}
}

// now execute the result, if we're supposed to
if (proxy.getExecuteResult()) {
executeResult();
}

executed = true;
}

return resultCode;
}
finally {
UtilTimerStack.pop(profileKey);
}
}

public String invokeActionOnly() throws Exception {
return invokeAction(getAction(), proxy.getConfig());
}


(Interceptor接口的定义)

public interface Interceptor extends Serializable {

/**
* Called to let an interceptor clean up any resources it has allocated.
*/
void destroy();

/**
* Called after an interceptor is created, but before any requests are processed using
* {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
* the Interceptor a chance to initialize any needed resources.
*/
void init();

/**
* Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
* request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
*
* @param invocation the action invocation
* @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
* @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
*/
String intercept(ActionInvocation invocation) throws Exception;

}
再来一个简单的实例源码:

public class MyInterceptor implements Interceptor {

public void destroy() {
// TODO Auto-generated method stub

}

public void init() {
// TODO Auto-generated method stub

}

public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("interceptor");
String result = invocation.invoke();
System.out.println("finshed");
return result;
}

}
我们可以看到:intercept方法里再次调用了ActionInvocation的invoke方法,这就相当与一个递归调用,也就实现了一系列拦截器前操作(如:System.out.println("interceptor");)的先执行,等到递归返回resultCode时逆序执行后操作(如:System.out.println("finshed");),故形成了流程图所展示的情况

(以上只是我的个人理解  有不对请指正和探讨 O(∩_∩)O)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: