這里我們只是講一下最基本的原理,也就是當(dāng)頁面請求提交過來之后struts2是怎樣處理的玄括。
在網(wǎng)上找了一張圖盈电,地址是:
http://blog.csdn.net/wuwenxiang91322/article/details/11070513
其中控制器就是
StrutsPrepareAndExecuteFilter或FilterDispatcher
沿癞。在Struts2.1以前調(diào)用FilterDispatcher
躁绸,Struts2.1以后調(diào)用StrutsPrepareAndExecuteFilter
,控制器通過ActionMapper
得到action
的相關(guān)信息枷莉,通過ActionProxy
去讀取相關(guān)配置文件娇昙,主要過程是在ActionInvocation(即DefaultActionInvocation)
和實(shí)際action
之間。我們就從控制器開始笤妙。
首先我們在org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
這個(gè)類的doFilter
方法開頭設(shè)置一個(gè)斷點(diǎn)冒掌,使用debug進(jìn)行跟蹤。在此方法中我們可以看到這樣一段:
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
說明:這里表示如果mapping為空表示沒有找到相應(yīng)的action蹲盘,否則表示找到了相應(yīng)的action股毫,找到之后執(zhí)行
execute.executeAction(request, response, mapping);
方法,我們跟進(jìn)去召衔,進(jìn)去之后會(huì)發(fā)現(xiàn)執(zhí)行的是方法:
dispatcher.serviceAction(request, response, mapping);
這個(gè)dispatcher
就是org.apache.struts2.dispatcher.Dispatcher
類铃诬,即執(zhí)行Dispatcher
類的serviceAction
方法,繼續(xù)跟進(jìn)去。這個(gè)方法為:
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws ServletException {
Map<String, Object> extraContext = createContextMap(request, response, mapping);
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
......
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
......
}
說明:
- 1.這個(gè)方法中我們首先看這兩行
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
可以看到struts2將值棧存到了request域中趣席,我們以后要想取得值棧中的內(nèi)容可以使用上面的常量兵志。
- 2.同時(shí)可以看到產(chǎn)生了一個(gè)
ActionProxy
對象,這個(gè)對象會(huì)通過ConfigurationManager
去讀取配置文件的相關(guān)信息吩坝,之后就會(huì)執(zhí)行其execute()
方法毒姨。跟蹤此方法會(huì)發(fā)現(xiàn)此方法最后
return invocation.invoke();
也就是執(zhí)行com.opensymphony.xwork2.DefaultActionInvocation
對象的invoke方法,而此類中我們可以看到包含了我們自己的action和一系列的攔截器(interceptor)钉寝。跟蹤此方法:
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
resultCode = invokeActionOnly();
}
說明:代碼中這樣一段可以看到首先執(zhí)行各類攔截器,當(dāng)攔截器執(zhí)行完之后執(zhí)行invokeAction()
這個(gè)方法闸迷。
首先我們看
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
這里調(diào)用的是攔截器的intercept
方法嵌纲,在此方法中我們可以看到
result = invocation.invoke();
也就是說繼續(xù)調(diào)用DefaultActionInvocation
的invoke
方法,這樣就會(huì)調(diào)用下一個(gè)攔截器腥沽,當(dāng)將所有攔截器都調(diào)用一遍之后逮走,才會(huì)執(zhí)行DefaultActionInvocation
的invokeActionOnly();
方法,我們跟進(jìn)去會(huì)發(fā)現(xiàn)執(zhí)行的是
return invokeAction(getAction(), proxy.getConfig());
在invokeAction
方法中:
String methodName = proxy.getMethod();
此時(shí)拿到的方法就是我們的action中的execute方法今阳,然后就執(zhí)行此方法师溅,之后就返回去,經(jīng)過一些列的攔截器之后返回到
com.opensymphony.xwork2.DefaultActionInvocation
然后返回到org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
類盾舌,最后在頁面中響應(yīng)墓臭。
最后:根據(jù)原理圖和debug調(diào)試基本上可以對struts的原理有個(gè)比較大概的了解了。