这个是过去版本的,但是大致执行流程是大同小异的。
首先struts2的入口就是,StrutsPrepareAndExecuteFilter,核心过滤器
首先会执行过滤器的init初始化方法
public void init(FilterConfig filterConfig) throws ServletException {
//初始化操作类
InitOperations init = new InitOperations();
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
//初始化分发器
dispatcher = init.initDispatcher(config);
//初始化静态资源加载器
init.initStaticContentLoader(config, dispatcher);
//初始化进行Http预处理的操作类
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
//初始化进行Http请求处理的逻辑执行的操作类
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
//自定义初始化过程,留待扩展
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
//初始化之中的清理工作
init.cleanup();
}
}
然后会跳转到doFilter()
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
//设置编码集
prepare.setEncodingAndLocale(request, response);
//创建ActionContext,ValueStack等
prepare.createActionContext(request, response);
//获取当前线程
prepare.assignDispatcherToThread();
if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
//包装request
request = prepare.wrapRequest(request);
//获取action,里面有切割uri的过程
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
//执行action,这也是struts2的核心部分
execute.executeAction(request, response, mapping);
}
}
} finally {
//清理request,ActionContext,Dispatcher等
prepare.cleanupRequest(request);
}
}
下面对execute.executeAction(request, response, mapping); 这个方法,进行源码分析。
点击进去进入ExecuteOperations类的executeAction(),只是个跳转。
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
dispatcher.serviceAction(request, response, servletContext, mapping);
}
点击serviceAction方法,进入Dispatcher类,也就是核心分发器。
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping) throws ServletException {
//创建Context
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放置于ThreadLocal中,创建线程副本,使其线程安全。
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();
//创建代理对象并且获取
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
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 {
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 {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not find action or result", e);
}
}
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
if (handleException || devMode) {
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} else {
throw new ServletException(e);
}
} finally {
UtilTimerStack.pop(timerKey);
}
}
点击createActionProxy()方法,进入DefaultActionProxyFactory,action代理工厂
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);
}
点击createActionProxy方法
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
container.inject(proxy);
proxy.prepare();
return proxy;
}
点击prepare()方法,进入DefaultActionProxy类
protected void prepare() {
String profileKey = "create DefaultActionProxy: ";
try {
UtilTimerStack.push(profileKey);
config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName);
if (config == null && unknownHandlerManager.hasUnknownHandlers()) {
config = unknownHandlerManager.handleUnknownAction(namespace, actionName);
}
if (config == null) {
throw new ConfigurationException(getErrorMessage());
}
resolveMethod();
if (!config.isAllowedMethod(method)) {
throw new ConfigurationException("Invalid method: " + method + " for action " + actionName);
}
//初始化
invocation.init(this);
} finally {
UtilTimerStack.pop(profileKey);
}
}
点击init()进入DefaultActionInvocation类
public void init(ActionProxy proxy) {
this.proxy = proxy;
Map<String, Object> contextMap = createContextMap();
// Setting this so that other classes, like object factories, can use the ActionProxy and other
// contextual information to operate
ActionContext actionContext = ActionContext.getContext();
if (actionContext != null) {
actionContext.setActionInvocation(this);
}
//创建action
createAction(contextMap);
if (pushAction) {
stack.push(action);
contextMap.put("action", action);
}
invocationContext = new ActionContext(contextMap);
invocationContext.setName(proxy.getActionName());
//创建拦截器栈,并且用迭代器的方式迭代
// get a new List so we don't get problems with the iterator if someone changes the list
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
}
点击createAction方法,在此处创建action的代理对象,源码深处是通过反射的方式获得的,在此不再赘述。
protected void createAction(Map<String, Object> contextMap) {
// load action
String timerKey = "actionCreate: " + proxy.getActionName();
try {
UtilTimerStack.push(timerKey);
action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
} catch (InstantiationException e) {
throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig());
} catch (IllegalAccessException e) {
throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig());
} catch (Exception e) {
String gripe;
if (proxy == null) {
gripe = "Whoa! No ActionProxy instance found in current ActionInvocation. This is bad ... very bad";
} else if (proxy.getConfig() == null) {
gripe = "Sheesh. Where'd that ActionProxy get to? I can't find it in the current ActionInvocation!?";
} else if (proxy.getConfig().getClassName() == null) {
gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
} else {
gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
}
gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]");
throw new XWorkException(gripe, e, proxy.getConfig());
} finally {
UtilTimerStack.pop(timerKey);
}
if (actionEventListener != null) {
action = actionEventListener.prepare(action, stack);
}
}
返回来,执行Dispatcher类中的 proxy.execute();,执行DefaultActionProxy中的execute(),执行invoke()方法完成迭代,执行拦截器栈中的拦截器。
public String execute() throws Exception {
ActionContext nestedContext = ActionContext.getContext();
ActionContext.setContext(invocation.getInvocationContext());
String retCode = null;
String profileKey = "execute: ";
try {
UtilTimerStack.push(profileKey);
retCode = invocation.invoke();
} finally {
if (cleanupContext) {
ActionContext.setContext(nestedContext);
}
UtilTimerStack.pop(profileKey);
}
return retCode;
}
拦截器执行完毕后,执行结果集
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping) throws ServletException {
.....
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
....
结果集执行完毕后,完成跳转,通常是jsp页面或者Freemarker,Velocity等模板技术实现的页面。
最后,倒叙执行拦截器,执行核心过滤器的cleanupRequest方法清除request,ActionContext,Dispatcher中的内容,然后response返回浏览器。
} finally {
prepare.cleanupRequest(request);
}