这篇文章我们主要关注的就是executeAction这个方法,对应源码中的位置如下:
我们继续往深了挖代码:
发现还是由dispatcher来处理,继续挖
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws ServletException {
Map<String, Object> extraContext = createContextMap(request, response, mapping);
// 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) {
// 如果没有值栈,就从Actioncontext对象中获取
stack = ctx.getValueStack();
}
}
if (stack != null) {
// 如果现在已经存在了,就新建一个值栈,并将旧值栈存入到新值栈中
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = "Handling request from Dispatcher";
try {
UtilTimerStack.push(timerKey);
// 获取命名空间,相当于struts.xml中的package
String namespace = mapping.getNamespace();
// 获取request请求中的action名称
String name = mapping.getName();
// 获取要执行的方法名称
String method = mapping.getMethod();
// 获取actionProxy对象
ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
// 将值栈存入到request域中
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
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if (!nullStack) {
// 更新request域中的值栈
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
logConfigurationException(request, e);
sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
if (handleException || devMode) {
sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} else {
throw new ServletException(e);
}
} finally {
UtilTimerStack.pop(timerKey);
}
}
分析以上代码可以发现
1.不管怎么都会更新requst域中的值栈
2.ActionProxy类的proxy对象很重要,但是由于这部分比较复杂,我打算留到下次再来分析
3.在执行action请求前会判断是否直接返回结果