public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
//設置編碼</span></strong>
prepare.setEncodingAndLocale(request, response);
</span>//創建actionContext
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
//如果不是struts的請求則繼續由其它過濾器執行
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
//包裝request,對有文件上傳的特殊處理下
</blockquote>
request = prepare.wrapRequest(request);
//查找對應的ActionMapping
</blockquote>
ActionMapping mapping = prepare.findActionMapping(request, response, true);
//如果找不到ActionMapping則當作靜態資源來處理
</blockquote>
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
//使用ActionMapping來執行action
</blockquote>
execute.executeAction(request, response, mapping);</strong>
}
}
} finally {
prepare.cleanupRequest(request);
}
}</span></td>
</tr>
</tbody>
</table>
跟蹤execute.executeAction(),則到了 org.apache.struts2.dispatcher.Dispatcher,如下:
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping) throws ServletException {
Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
boolean nullStack = stack == null;
if (nullStack) {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
}
if (stack != null) {
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = "Handling request from Dispatcher";
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
Configuration config = configurationManager.getConfiguration();
//使用StrutsActionProxyFactory(ActionProxyFactory的一個實現)創建action代理對象
//proxy實際上是org.apache.struts2.impl.StrutsActionProxy類型
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);</strong></span>
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
//執行action
</blockquote>
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if (!nullStack) {
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
// WW-2874 Only log error if in devMode
if(devMode) {
String reqStr = request.getRequestURI();
if (request.getQueryString() != null) {
reqStr = reqStr + "?" + request.getQueryString();
}
LOG.error("Could not find action or result\n" + reqStr, e);
}
else {
LOG.warn("Could not find action or result", e);
}
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} finally {
UtilTimerStack.pop(timerKey);
}
}</td>
</tr>
</tbody>
</table>
DefaultActionProxyFactory創建ActionProxy,在com.opensymphony.xwork2.DefaultActionProxyFactory:
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {
ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
container.inject(inv);
return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
} |
</tr>
</tbody>
</table>
接下來看看 org.apache.struts2.impl.StrutsActionProxy的execute()方法,如下:
</span>
public String execute() throws Exception {
ActionContext previous = ActionContext.getContext();
ActionContext.setContext(invocation.getInvocationContext());
try { //這里就是調用攔截器的入口了
return invocation.invoke();
} finally {
if (cleanupContext)
ActionContext.setContext(previous);
}
} |
</tr>
</tbody>
</table>
最關鍵的,com.opensymphony.xwork2.DefaultActionInvocation.invoke()方法,這個DefaultActionInvocation是ActionInvocation的一個實現類,如下: | |