Struts2框架的执行流程

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

你可能感兴趣的:(Struts2框架的执行流程)