Struts2框架的执行流程
1.struts2的流程图2.描述执行流程( 1).客户端初始化一个指向Servlet容器(例如Tomcat)的请求 (客户端提交一个HttpServletRequest请求。)(2)请求被提交到一系列的过滤器(Filter)。如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher。注...
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)
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="datetime"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
最后不满足if中的条件会执行 resultCode = invokeActionOnly()
注意:这时还没有给客户端应答,只是生成了页面 最后,按照相反的顺序把interceptor执行完,最后传给response展示结果。
更多推荐
所有评论(0)