[Java面試四]Strust2總結及在面試中的一些問題.


1. JavaEE軟件三層結構和MVC的區別?

JavaEE軟件三層機構是由sun公司提供JavaEE開發規范的:Web(表現層)、業務邏輯層、數據持久層。【其中WEB層會使用前端控制器模式】
MVC是一種思想,是一種模式,將軟件分為 Model模型、View視圖、Controller控制器。【JavaEE開發更強調三層結構,web層開發更注重MVC
Struts2 就是web層開發框架
,符合MVC模式;struts1 webwork jsf SpringMVC 都是MVC

2. Struts和struts2的區別有哪些?

Action類 
Struts 1要求Action類要擴展自一個抽象基類。Struts 1的一個共有的問題是面向抽象類編程而不是面向接口編程。
Struts 2的Action類實現了一個Action接口,連同其他接口一起實現可選擇和自定義的服務。Struts 2提供一個名叫ActionSupport的基類實現一般使用的接口。雖然,Action接口不是必須的。任何使用execute方法的POJO對象可以 被當作Struts 2Action對象使用。 
程模型
Struts 1 Action類是單例類,因只有一個示例控制所有的請求。單例類策略造成了一定的限制且給開發帶來了額外的煩惱。Action資源必須是程安全或者同步 的。
Struts 2 Action對象每一個請求都實例化對象,所以沒有程安全的問題。(實踐中,servlet容器生許多丟的對象對於每一個請求,多於一個的對象並不影響垃 圾收集)
Servlet 依賴
Struts 1的Action類依賴於servlet APIHttpServletRequestHttpServletResponse作參數傳給execute方法當Action被調用時。
Struts 2的Action不和容器有關。Servlet上下文被表現簡單的Maps,允許Action被獨立的測試。Struts 2Action可以訪問最初的請求和相應,如果需要的話。然而,其他的架構元素少或者排除直接訪問HttpServletRequest或者 HttpServletResponse的需要。 
易測性
測試Struts 1的主要障礙是execute方法暴露了Servlet API。第三方的擴展,Struts測試用例,提供Struts 1的集合對象。
Struts 2的Action可以通過實例化Action測試,設置屬性,然后調用方法。依賴注入的支持也是測試變得更簡單。
接受輸入
Struts 1使用ActionForm對象捕獲輸入。象Action一樣,所有的ActionForm必須擴展基類。因其他的JavaBean不能作 ActionForm使用,開發者經常創建多余的類捕獲輸入。DynaBeans可以被用來作替代ActionForm的類創建。但是開發者可以重新描述 已經存在的JavaBean
Struts 2 Action屬性作輸入屬性,排除第二個輸入對象的需要。輸入屬性可能有豐富的對象類型這些類型有他們自己的屬性。Action的屬性可以通過標簽庫訪 問。Struts 2也支持ActionForm形式。豐富的對象類型,包含業務或者域對象,可以被當作輸入或者輸出對象使用。饃型驅動特性簡化標簽對POJO輸入對象的引 用。
表達式語言
Struts 1整和JSTL,所以它使用JSTL的表達式語言。表達式語言有基本的圖形對象移動,但是相對很弱的集合和被索引的屬性支持。
Struts 2使用JSTL,但是框架也支持更大和更靈活的表達式,叫做對象圖形符號語言OGNL)。
將值綁定要視圖上
Struts 1使用標准JSP機制來綁定對象到頁面上下文。
Struts 2使用“ValueStack”技術了標簽庫可以不用鏈接你的視圖到對象的表現類型訪問值。ValueStack策略允許重用視圖。
類型轉換
Struts 1的ActionForm屬性經常都是String的。Struts 1使用Commons-Beanutils類型轉換。轉換每一個類,不是每一個實例配置。
Struts 2使用OGNL類型轉換。框架包含轉換器基本的和共同的對象類型和原始類型。
驗證
Struts 1支持手動驗證憑借ActionFormvalidate方法,或者通過擴展的公用驗證器。類可以有不同的驗證上下文未相同的類,但是不能不能包括驗證 子對象。
Struts 2支持手動驗證憑借validate方法和XWork驗證框架。Xwork驗證框架支持一連串的驗證子屬性使用的驗證了屬性類的類型和嚴正上下文而定義。
Action執行的控制
Struts 1支持獨立的請求處理器對於每一個模型,但是所有在模型中的Action必須共享同一個生命周期。
Struts 2支持在每一個Action基礎上憑借攔截棧創建不同的生命周期。自定義棧可以被創建且使用不同的所需 的Action

3. 簡要說說Struts2的處理流程

Struts2框架的大致處理流程如下:
1、加載類(FilterDispatcher
2、讀取配置(struts配置文件中的Action
3、派發請求(客戶端發送請求)
4、調用ActionFilterDispatcherstruts配置文件中讀取與之相對應的Action
5、啟用攔截器(WebWork攔截器鏈自動對請求應用通用功能,如驗證)
6、處理業務(回調Actionexecute()方法)
7、返回響應(通過execute方法將信息返回到FilterDispatcher
8、查找響應(FilterDispatcher根據配置查找響應的是什么信息如:SUCCESSERROER,將跳轉到哪個jsp頁面)
9、響應用戶(jsp--->客戶瀏覽器端顯示)
10struts2標簽庫(相比struts1的標簽庫,struts2是大大加強了,對數據的操作功能很強大)

wps5845.tmp9d4c8f2b-8f7e-48bf-87c4-d3ea4b65b8ba 

請求(.action)---->經過StrutsPrepareAndExecuteFilter 核心控制器---->進入到Struts2的攔截器Interceptor(實現代碼功能)----->通過action的名稱找對應的Action----->執行Action類的execute方法----->通過execute方法中返回的字符串,在Struts.xml中找對應的結果頁面(result)【在action執行之前,執行了defaultStack攔截器棧

* 攔截器 在 struts-default.xml定義 【它位於sruts2-core-xxx.jar目錄下

* 執行攔截器 是 defaultStack 中引用攔截器

4、Struts2配置文件加載順序

    通過查看StrutsPrepareAndExecuteFilter源碼可以得到答案!
        82dc781d-960c-4ea8-81d9-9055e7e9c44c    
    此處,我們以及清晰了看到了該類加載配置文件的順序,我們依次圍繞標號查看對應方法產生的文件即可。

 

    be5b51bc-149e-4e9a-baaf-1db4992d7cf9
    對應產生文件依次如下:

 

   init_DefaultProperties(); // [1]----  org/apache/struts2/default.properties
 
    init_TraditionalXmlConfigurations(); // [2] --- struts-default.xml,struts-plugin.xml,struts.xml
 
    init_LegacyStrutsProperties(); // [3] --- 自定義struts.properties
 
    init_CustomConfigurationProviders(); // [5]  ----- 自定義配置提供
 
    init_FilterInitParameters() ; // [6] ----- web.xml
 
    init_AliasStandardObjects() ; // [7] ---- Bean加載
結論   :【前三個是默認的,不用關注,后面三個需要注意】

 

     default.properties  該文件保存在 struts2-core-2.3.7.jar org.apache.struts2包里面  (常量的默認值)
   
 struts-default.xml 該文件保存在 struts2-core-2.3.7.jar  Bean 、攔截器、結果類型  
   
 struts-plugin.xml  該文件保存在 struts-Xxx-2.3.7.jar  (在插件包中存在   ,配置插件信息   struts-config-browser-plugin-2.3.7.jar 里面有
   
 struts.xml  該文件是 web應用默認的struts 配置文件   (實際開發中,通常寫 struts.xml
   
 struts.properties  該文件是 Struts的默認配置文件  (配置常量 )
     web.xml  該文件是 Web應用的配置文件 (配置常量 )

后加載配置文件中修改的常量的值會覆蓋前面配置文件修改的常量的值!

5、我們在書寫Action的時候有哪幾種方式?他們有什么區別?

有三種方式:
     普通POJO(簡單Java對象),這種方式我們不需要繼承任何父類,實現任何接口。Struts2框架讀取struts.xml文件,獲得完整的action類名。
  1. obj =Class.forName("完整類名").newInstance();
  2. Method m =Class.forName("完整類名").getMethod("execute");
  3. m.invoke(obj);//通過反射 執行execute()方法
    編寫Action實現Action接口
  1. Action接口中,定義默認五種邏輯視圖名稱
  2. // 數據處理成功 (成功頁面)
  3. publicstatic final String SUCCESS ="success";
  4. // 頁面不跳轉 return null; 效果一樣
  5. publicstatic final String NONE ="none";
  6. // 數據處理發送錯誤 (錯誤頁面)
  7. publicstatic final String ERROR ="error";
  8. // 用戶輸入數據有誤,通常用於表單數據校驗 (輸入頁面)
  9. publicstatic final String INPUT ="input";
  10. // 主要權限認證 (登陸頁面)
  11. publicstatic final String LOGIN ="login";
    編寫Action繼承ActionSupport(推薦)
在Action中使用表單校驗、錯誤信息設置、讀取國際化信息三個功能
  1. 代理模式,控制目標對象訪問
  2. /hello.action 請求時StrutsPrepareAndExecuteFilter doFilter一定執行
  3. //判斷配置文件中有沒有對應Action
  4. ActionMapping mapping = prepare.findActionMapping(request, response,true);
  5. //根據配置創建代理對象
  6. ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext,true,false);
  7. 執行時:先執行interceptorintercept攔截方法,最后指向actionexecute

6、Action是如何接受請求參數的?

屬性驅動和模型驅動  
Struts2內部提供了參數封裝功能,不需要使用BeanUtils進行封裝。Struts2大部分內置功能都是攔截器實現的。
    a1fbe5b3-bf27-47fa-8d05-dc7e5a4daa8d
    當點擊登錄提交表單時,就會被下面的攔截器進行封裝,進行set注入值,實現參數封裝。
<interceptor name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
 
第一種 :Action 本身作為model對象,通過成員setter封裝 (屬性驅動 )
    主要用於參數較少的封裝,如果分層,不利於將數據傳遞到業務層。
    頁面:       
用戶名:<inputtype="text"name="username"/><br/>
    Action:
publicclassRegistAction1extendsActionSupport{
privateString username;
publicvoid setUsername(String username){
this.username = username;
}
}
    Struts2 action是多實例,不會有線程安全問題,使用這種數據封裝方式,數據封裝到action屬性中,不能將action對象傳遞給業務層,我們需要再單獨定義javabean,將action屬性封裝到javabean。
 
第二種 :創建獨立model對象,頁面通過ognl表達式封裝 (屬性驅動)
    具體封裝流程如下:傳遞username,調用setUsername,把username注入User中,將會新建一個User對象,當第二個參數password傳遞過來時,struts框架將首先調用getUser方法詢問User是否為空,如果為空,將會新建一個User,否則不會新建,直接注入值。如果只有一個Set方法,那么每set一次數據,就會新建一個User對象,那么就是把usernamepassword封裝在兩個不同的User 對象中了。這樣封裝失敗。
    頁面:
<!--基於OGNL表達式的寫法-->
用戶名:<inputtype="text"name="user.username"/><br/>
密 碼:<inputtype="password"name="user.password"/><br/>
    model(User):
publicclassUser{
privateString username;
privateString password;
publicString getUsername(){
return username;
}
publicvoid setUsername(String username){
this.username = username;
}
publicString getPassword(){
return password;
}
publicvoid setPassword(String password){
this.password = password;
}
}
    Action:
publicclassRegistAction2extendsActionSupport{
    privateUser user;
publicvoid setUser(User user){
    this.user = user;
}
//必須提供get方法(封裝第一個參數時,創建新的User對象, 封裝第二個參數需要使用第一個創建user對象)
publicUser getUser(){
    return user;
    }
}
    由params的攔截器完成參數的封裝
<interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
 
第三種 :使用ModelDriven接口,對請求數據進行封裝 (模型驅動 ) ----- 企業開發的主流(模型驅動有很多特性)
<interceptorname="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 為模型驅動提供了更多特性
    頁面:
用戶名:<inputtype="text"name="username"/><br/> 
    model(User):
   
    Action :
publicclassRegistAction3extendsActionSupportimplementsModelDriven<User>{
// 模型對象必須手動實例化
    privateUser user =newUser();
publicUser getModel(){
    return user;
}
}
    對比第二種、第三種 : 第三種只能在Action中指定一個model對象(返回一個model對象),第二種可以在Action中定義多個model對象
<inputtype="text"name="user.username"/> 
<inputtype="text"name="product.info"/>

 

7、Action的相關配置?

  1 必須要為<action>元素 配置<package>元素  struts2 圍繞package進行Action的相關配置 

    配置package 三個常用屬性

 

<packagename="default"namespace="/"extends="struts-default">
    name包名稱,在struts2的配置文件中,包名不能重復,name並不是真正包名,只是為了管理 Action

 

    namespace <action>name屬性,決定 Action的訪問路徑  (以/開始 

       namespace=""        :默認的名稱空間
        namespace="/"       :根名稱空間
        namespace="/aa/"
    :帶有名稱空間的路徑

    extends繼承哪個包,通常開發中繼承struts-default  struts-default包在 struts-default.xml中定義 )【可以使用包中默認的攔截器和結果集】

    2Action是通過<action>元素配置

 

<action name="hello"class="cn.itcast.struts2.demo1.HelloAction" method="execute">
    <action> name <package>namespace屬性共同決定 Action 的訪問路徑
    class:類全路徑
    method:執行的方法,默認為execute()方法

 

例如:

 

<package name="default"namespace="/user" extends="struts-default">
    <action name="hello"class="cn.itcast.struts2.demo1.HelloAction">
        <result name="success">/demo1/success.jsp</result>
    </action>
</package>
此時的訪問路徑 http://localhost:8080/Struts2/demo1/user/hello.action
    result中的name:結果頁面邏輯視圖名稱,默認為success
    type:結果類型(后面會做詳細介紹,默認為轉發)

 

3) <action> 元素配置默認值

    <package> namespace 默認值 /
    <action>
class 默認值 ActionSupport      <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />   
    <result> name 默認值
success

8、Action訪問Servlet API有哪幾種方式,簡單的介紹一下

.方式一:使用ActionContext對象(在Action中解耦合方式間接訪問Servlet API)
    在struts2中Action API已經與Servlet API 解耦合(沒有依賴關系), 開發簡單,便於測試。
    Servlet API 常見操作 : 表單提交請求參數獲取,向request、session、application三個范圍存取數據  
.方式二:使用接口注入的方式操作Servlet API(藕合)
    通過 Aware接口,在構造Action時,自動注入需要操作Servlet對象(需要哪個對象就實現哪個Aware接口 )
.方式三:在Action中直接通過 ServletActionContext 獲得Servlet API
    靜態方法返回request,不會有線程問題(使用了ThreadLocal來實現的)
總結:理論來說,第一種方式最好,實現了解耦和,但是第三種我們使用最為簡單,企業中沒有很大的限制,自己熟悉哪種就使用哪種。

9. 說說Struts2的輸入校驗流程

Struts2校驗框架進行校驗時,將執行以下流程:
A:類型轉換器負責對字符串的請求參數執行類型轉換,並將這些值設置成Action的屬性值
B:在執行類型轉換過程中可能出現異常,如果出現異常,將異常信息保存到ActionContext中,convertionError攔截器將負責將其封裝到fieldError里,如果沒有異常,直接進入第3
C:調用Struts2的內置校驗規則進行輸入校驗
D:通過反射調用validateXXX()方法
E:調用Action類中的validate()方法
F:如果上面的幾步中沒有出FiledError,就調用Acton中的邏輯處理方法,如果有,則進入input視圖
所以,在進行校驗時,別忘記在Action中的配置名為input的結果如:<result name=input>validate.jsp</result>

10. Struts2 form標簽數據為什么可以回顯?

221e0239-ad18-4104-8809-3d21ff0545e1

11. 什么是值棧?值棧的內部結構?

    ValueStack 是 struts2 提供一個接口,實現類 OgnlValueStack ---- 值棧對象 (OGNL是從值棧中獲取數據的 )每個Action實例都有一個ValueStack對象 (一個請求對應 一個ValueStack對象 )在其中保存當前Action 對象和其他相關對象 (值棧中是有Action引用的 )Struts 框架把 ValueStack 對象保存在名“struts.valueStack” 的請求屬性中,request中(值棧對象是request一個屬性)

fc54671a-5c84-4d5f-bae5-c1fe7c10a96d

    值棧由兩部分組成,ObjectStack和ContextMap
ObjectStack: Struts 把動作和相關對象壓入 ObjectStack --List
ContextMap: Struts 把各種各樣的映射關系(一些 Map 類型的對象) 壓入ContextMap Struts 會把下面這些映射壓入 ContextMap
parameters: 該 Map 中包含當前請求的請求參數
request: 該 Map 中包含當前 request 對象中的所有屬性
session: 該 Map 中包含當前 session 對象中的所有屬性
application:該 Map 中包含當前 application  對象中的所有屬性
attr: Map 按如下順序來檢索某個屬性: request, session, application
 
VaValueStack中 存在root屬性 (CompoundRoot) 、 context 屬性 (OgnlContext )
    * CompoundRoot 就是ArrayList
    * OgnlContext 就是 Map
cncontext 對應Map 引入 root對象
    * context中還存在 request、 session、application、 attr、 parameters 對象引用
    * OGNL表達式,訪問root中數據時 不需要 #, 訪問 request、 session、application、 attr、 parameters 對象數據 必須寫 #
    * 操作值棧 默認指 操作 root 元素

12. 值棧對象的創建 ,ValueStack 和 ActionContext 是什么關系 ?

值棧對象是請求時創建的
doFilter中 prepare.createActionContext(request, response);
    * 創建ActionContext對象過程中,創建值棧對象ValueStack
    * ActionContext對象對ValueStack對象有引用的(在程序中通過 ActionContext 獲得值棧對象 )
Dispatcher類 serviceAction 方法中將值棧對象保存到request范圍
    request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

13.如何獲得值棧對象?

獲得值棧對象 有兩種方法
    ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    ValueStack valueStack2 = ActionContext.getContext().getValueStack();

14.如何向值棧中保存數據?如何在jsp頁面中獲取值棧的數據?

兩種方式
    // 將數據保存root的索引0位置,放置到第一個元素 ArrayList add(0,element);
    valueStack.push("itcast");
    // 在值棧創建參數map, 將數據保存到map中
    valueStack.set("company", "傳智播客");
在jsp中 通過 <s:debug /> 查看值棧的內容

wps47E6.tmpf2c502e0-4ca5-4aff-8a59-31d4f84bc177 

 
 
獲取值棧數據時,如果訪問root中數據不需要# ,訪問其它對象數據加 #
通過下標獲取root中對象
<s:property value="[0].top"/> //取值棧頂對象
直接在root中查找對象屬性 (自上而下自動查找)
valueStack:<s:property value="username"/>
 
在OgnlContext中獲取數據
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>

15.為什么EL也能訪問值棧中的數據?

StrutsPreparedAndExecuteFilter的doFilter代碼中 request = prepare.wrapRequest(request); 
* 對Request對象進行了包裝 ,StrutsRequestWrapper
* 重寫request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
    attribute = stack.findValue(s);
}
訪問request范圍的數據時,如果數據找不到,去值棧中找

16.你在開發中,值棧主要有哪些應用?

值棧主要解決Action向JSP傳遞數據問題
Action 向JSP 傳遞數據處理結果 ,結果數據有兩種形式
1)消息 String類型數據
this.addFieldError("msg", "字段錯誤信息");
this.addActionError("Action全局錯誤信息");
this.addActionMessage("Action的消息信息");
* fieldError 針對某一個字段錯誤信息 (常用於表單校驗)、actionError (普通錯誤信息,不針對某一個字段 登陸失敗)、 actionMessage 通用消息 
 
在jsp中使用 struts2提供標簽 顯示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
 
2)數據 (復雜類型數據)
使用值棧  valueStack.push(products);
哪些數據默認會放入到值棧 ???
1)每次請求,訪問Action對象 會被壓入值棧 ------- DefaultActionInvocation 的 init方法 stack.push(action);
    * Action如果想傳遞數據給 JSP,只有將數據保存到成員變量,並且提供get方法就可以了
2)ModelDriven 接口有一個單獨攔截器
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
在攔截器中,將model對象壓入了值棧 stack.push(model);
    * 如果Action 實現ModelDriven接口,值棧默認棧頂對象就是model對象

17.如何防止表單重復提交?

哪些情況會導致重復提交?
    服務器處理服務后,轉發頁面,客戶端點擊刷新(重定向)
    客戶端網絡過慢,按鈕連續點擊(按鈕點擊一次后,禁用按鈕)
使用令牌機制
b427a734-9313-4184-8f56-e1ed7ec248a0

18.簡單的說一下ActionProxy的運行原理?

Struts2的攔截器的本質就是AOP思想,而AOP就是基於代理模式。
6d59bb08-7c9c-4357-8d60-33e4ae386272

19.攔截器和過濾器有什么區別?

1、① 攔截器是基於java的反射機制的,而過濾器是基於函數回調
2、 過濾器依賴與servlet容器,而攔截器不依賴與servlet容器
3、 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用
4、 攔截器可以訪問action上下文、值棧里的對象,而過濾器不能
5、 在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次
攔  攔截器 :是在面向切面編程的就是在你的service或者一個方法,前調用一個方法,或者在方法后調用一個方法比如動態代理就是攔截器的簡單實現,在你調用方法前打印出字符串(或者做其它業務邏輯的操作),也可以在你調用方法后打印出字符串,甚至在你拋出異常的時候做業務邏輯的操作。

20.Struts2詳細運行流程

1a8db227-399d-420f-9baa-b8f699e8e08b
    請求首先通過Filter chain,Filter主要包括ActionContextCleanUp,它主要清理當前線程的ActionContext和Dispatcher;FilterDispatcher主要通過AcionMapper來決定需要調用哪個Action。
    ActionMapper取得了ActionMapping后,在Dispatcher的serviceAction方法里創建ActionProxy,ActionProxy創建ActionInvocation,然后ActionInvocation調用Interceptors,執行Action本身,創建Result並返回,當然,如果要在返回之前做些什么,可以實現PreResultListener。
 
部分類介紹
    ActionMapper
    ActionMapper其實是HttpServletRequest和Action調用請求的一個映射,它屏蔽了Action對於Request等java Servlet類的依賴。Struts2中它的默認實現類是DefaultActionMapper,ActionMapper很大的用處可以根據自己的需要來設計url格式,它自己也有Restful的實現,具體可以參考文檔的docs\actionmapper.html。
     ActionProxy&ActionInvocation
    Action的一個代理,由ActionProxyFactory創建,它本身不包括Action實例,默認實現DefaultActionProxy是由ActionInvocation持有Action實例。ActionProxy作用是如何取得Action,無論是本地還是遠程。而ActionInvocation的作用是如何執行Action,攔截器的功能就是在ActionInvocation中實現的。
    ConfigurationProvider&Configuration
    ConfigurationProvider就是Struts2中配置文件的解析器,Struts2中的配置文件主要是尤其實現類XmlConfigurationProvider及其子類StrutsXmlConfigurationProvider來解析。
 
Struts2請求流程
    1、客戶端發送請求
    2、請求先通過ActionContextCleanUp-->FilterDispatcher
    3、FilterDispatcher通過ActionMapper來決定這個Request需要調用哪個Action
    4、如果ActionMapper決定調用某個Action,FilterDispatcher把請求的處理交給ActionProxy,這兒已經轉到它的Delegate--Dispatcher來執行
    5、ActionProxy根據ActionMapping和ConfigurationManager找到需要調用的Action類
    6、ActionProxy創建一個ActionInvocation的實例
    7、ActionInvocation調用真正的Action,當然這涉及到相關攔截器的調用
    8、Action執行完畢,ActionInvocation創建Result並返回,當然,如果要在返回之前做些什么,可以實現PreResultListener。添加PreResultListener可以在Interceptor中實現。
 
源代碼分析
     啟動服務器(tomcat)將會自動加載配置文件,加載過程如下:
        服務器啟動,init()方法被執行
    f419c63f-0661-4a59-8e42-5ad749c7dc79
    客戶端初始化一個指向Servlet容器(WEB容器)的請求;
 
    這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其他框架的集成很有幫助,例如:(SiteMesh Plugin)。

    接着StrutsPrepareAndExecuteFilter被調用,StrutsPrepareAndExecuteFilter詢問ActionMapper來決定這個請求是否需要調用某個Action。
    1e88f4ef-8221-43cb-8a30-623b22914f11
 
    如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy。 ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
    86e6da23-691b-4d67-9e7e-f32845dfb909
   
    ActionProxy創建一個ActionInvocation的實例。ActionInvocation實例使用命名模式來調用,在調用Action的過程前后,涉及到相關攔截器(Intercepter)的調用。攔截器默認執行<default-interceptor-ref name="defaultStack"/>defaultStack里面有一系列的interceptor。
 
    一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。在表示的過程中可以使用Struts2框架中繼承的標簽。在這個過程中需要涉及到ActionMapper,響應的返回是通過我們在web.xml中配置的過濾器 
 
    如果ActionContextCleanUp是當前使用的,則FilterDispatecher將不會清理threadlocal ActionContext;如果ActionContextCleanUp不使用,則將會去清理threadlocals。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM