1.struts2的流程图
2.描述执行流程
( 1 ). 客户端初始化一个指向Servlet容器(例如Tomcat)的请求 (客户端提交一个HttpServletRequest请求。)
(2)请求被提交到一系列的过滤器(Filter)。
如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher。注意:这里是有顺序的,先ActionContext CleanUp,再其他过滤器(Othter Filters、SiteMesh等),最后到FilterDispatcher。
FilterDispatcher是控制器的核心,就是MVC的Struts 2实现中控制层(Controller)的核心。
常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher。
(3)FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(HttpServlet Request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy。
(4) ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类。
(5)ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action。(有点类似与递归操作),但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)。
(6)Action执行完毕后,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。
3.简单的过一遍源码
StrutsPrepareAndExecuteFilter类中的doFilter方法,需要注意这几行。
89行 prepare.createActionContext(request, response);
//准备数据中心ActionContext.
91行 request = prepare.wrapRequest(request);
//进入对应的类(StrutsRequestWrapper)中注意 getAttribute(String key)方法,该方法会先从原声的request中查找,如果查找不到会再从ValueStack中查找。
92行 ActionMapping mapping = prepare.findActionMapping(request, response, true);
//解析对应的action相关信息
99行 execute.executeAction(request, response, mapping);
//该方法会调用Dispatcher类中的serviceAction方法
在该方法中注意:
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
proxy.execute();
//该方法会调用StrutsActionProxy中的execute方法
//在execute方法中
invocation.invoke()
//该方法会调用DefaultActionInvocation中的invoke
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 {
//注意:当执行玩所有的interceptor后,最后执行action
resultCode = invokeActionOnly();
}
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this)
//这句代码第一次会调用com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor中的intercept方法,在该方法中
result = invocation.invoke();
会又调用DefaultActionInvocation中的invoke() 。
如此递归的调用下去,
但是调用时会遵循一下的方式相互调用(ActionInvocation调Interceptor,Interceptor调ActionInvocation)
name="defaultStack">
ref name="exception"/>
ref name="alias"/>
ref name="servletConfig"/>
ref name="i18n"/>
ref name="prepare"/>
ref name="chain"/>
ref name="scopedModelDriven"/>
ref name="modelDriven"/>
ref name="fileUpload"/>
ref name="checkbox"/>
ref name="datetime"/>
ref name="multiselect"/>
ref name="staticParams"/>
ref name="actionMappingParams"/>
ref name="params"/>
ref name="conversionError"/>
ref name="validation">
name="excludeMethods">input,back,cancel,browse
ref>
ref name="workflow">
name="excludeMethods">input,back,cancel,browse
ref>
ref name="debugging"/>
ref name="deprecation"/>
最后不满足if中的条件会执行 resultCode = invokeActionOnly()
注意:这时还没有给客户端应答,只是生成了页面 最后,按照相反的顺序把interceptor执行完,最后传给response展示结果。
部分内容参考https://blog.csdn.net/snow_7/article/details/51513381