1. 程式人生 > >Struts2框架的執行流程

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)

  <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展示結果。