Struts1與Struts2原理

1.struts1和struts2 是2個完全不同的框架,其實struts2核心就是 webwork框架
struts1以ActionServlet作爲核心控制器,由ActionServlet負責攔截用戶的所有請求。Struts 1框架有3個重要組成部分:Action、ActionForm和ActionForward對象。ActionForm必須實現ActionForm的基類,設計上並不是真正的POJO。
struts2核心控制器是FilterDispatcher,Struts 2用於處理用戶請求的Action實例,並不是用戶實現的業務控制器,而是Action代理——因爲用戶實現的業務控制器並沒有與Servlet API耦合,顯然無法處理用戶請求。而Struts 2框架提供了系列攔截器,該系列攔截器負責將HttpServletRequest請求中的請求參數解析出來,傳入到Action中,並回調Action的execute方法來處理用戶請求。顯然,上面的處理過程是典型的AOP(面向切面編程)處理方式。
2.先說一下struts2的工作流程: 
核心控制器FilterDispatcher是Struts 2框架的基礎,包含了框架內部的控制流程和處理機制。 
業務控制器Action和業務邏輯組件是需要用戶來自己實現的。用戶在開發Action和業務邏輯組件 
的同時,還需要編寫相關的配置文件,供核心控制器FilterDispatcher來使用。 
Struts 2的工作流程相對於Struts 1要簡單,與WebWork框架基本相同,所以說Struts 2是 
WebWork的升級版本。Struts 2框架按照模塊來劃分,可以分爲Servlet Filters、Struts核心模 
塊、攔截器和用戶實現部分。Struts 2框架結構圖如圖3.1所示。 
一個請求在Struts 2框架中的處理大概分爲以下幾個步驟。 
客戶端提交一個(HttpServletRequest)請求,如上文在瀏覽器中輸入 http://localhost:
8080/bookcode/ch2/Reg.action就是提交一個(HttpServletRequest)請求。 
請求被提交到一系列(主要是3層)的過濾器(Filter),如(ActionContextCleanUp、其他過 
濾器(SiteMesh等)、 FilterDispatcher)。注意:這裏是有順序的,先ActionContext 
CleanUp,再其他過濾器(Othter Filters、SiteMesh等),最後到FilterDispatcher。 
FilterDispatcher是控制器的核心,就是MVC的Struts 2實現中控制層(Controller)的核心。 
FilterDispatcher詢問ActionMapper是否需要調用某個Action來處理這個(HttpServlet 
Request)請求,如果ActionMapper決定需要調用某個Action,FilterDispatcher則把請求的處 
理交給ActionProxy。 
ActionProxy通過Configuration Manager(struts.xml)詢問框架的配置文件,找到需要調用的 
Action類。例如,用戶註冊示例將找到UserReg類。
ActionProxy創建一個ActionInvocation實例,同時ActionInvocation通過代理模式調用Action 
。但在調用之前,ActionInvocation會根據配置加載Action相關的所有Interceptor(攔截器) 。
一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果 
result。 
3.說完struts2還應該說一下struts1的工作原理: 

 由ActionForm和JavaBean組成,其中ActionForm用於封裝用戶的請求參數,封裝成ActionForm 

對象,該對象被ActionServlet轉發給Action,Action根據ActionFrom裏面的請求參數處理用戶 

的請求。把我看到的和知道的整理出來。 

對於採用Struts框架的Web應用,在Web應用啓動時就會加載並初始化ActionServlet,ActionServlet從struts-config.xml文件中讀取配置信息,把它們存放到各種配置對象中,例如Action的映射信息存放在ActionMapping對象中。(struts的配置文件struts-config.xml:一個用戶請求是通過ActionServlet來處理和轉發的。那麼,ActionServlet如何決定把用戶請求轉發給哪個Action對象呢?這就需要一些描述用戶請求路徑和Action映射關係的配置信息了。在Struts中,這些配置映射信息都存放在特定的XML文件struts-config.xml中。在該配置文件中,每一個Action的映射信息都通過一個元素來配置。這些配置信息在系統啓動的時候被讀入內存,供Struts在運行期間使用。在內存中,每一個元素都對應一個org.apache.struts.aciton.ActionMapping的實例) 

/********************** 

用戶通過客戶端向服務器發出一個請求,而我們已經在web.xml配置了所有符合某某格式的請求都將由指定的Servlet來處理。比如說:只要是以.do結尾的請求(*.do)都由org.apache.struts.action.ActionServlet來對其進行處理。而ActionServlet和ActionMapping都已經在服務器啓動的時候被加載到內存裏面。 

結合登錄例子: 

當用戶登錄時,地址欄的URL爲:http://localhost:8080/struts_login/login.do


ActionServlet會拿到用戶的請求,並且去分析這個URL,它會截下/login(不包含.do)這一部分,截來之後,它的目的是爲了去struts-config.xml這個配置文件裏面找標籤path屬性的值等於所截部分的那個Action。找到之後,ActionServlet會把表單提交的數據給存放到ActionForm上,那ActionServlet又是怎麼找到ActionForm的呢?因爲Action標籤裏面有一個屬性是name,它的值就是所要找的ActionForm的名字,這樣ActionServlet會去上面的標籤裏面找(注意不是)標籤裏面的name屬性的值是與Action標籤裏面的name的值相等的,然後根據裏面type屬性的值,也就是所指的對象new一個實例,再把表單上相應的數據set進去。同時把標籤裏面的東西放到繼承Action類的那個指定類(本例子用的是LoginAction)的public ActionForward execute(ActionMapping mapping, ActionForm form, 

HttpServletRequest request, HttpServletResponse response) 

throws Exception 

這個方法裏面參數mapping裏面去,放好之後,再去調用我們自己寫的類(LoginAction),並把mapping,form,request,response作爲參數傳到execute方法裏面去。 

至於如何轉向的問題:這是由Struts完成的,只要你的execute能返回一個ActionForward對象,並且裏面包含有轉向的信息,Struts就會根據參數(mapping.findForward("success")裏面的"success")去找相應配置文件(struts-config.xml)裏面的相應標籤(),然後再由Struts框架決定轉向誰。由於上面已經說過,整個轉向的相關信息已經存放在mapping裏面,所以mapping.findForward("success")能夠找到相應的標籤。 

*/--這部是我自己增加的,其餘都是出自《精通Struts基於MVC的Java.Web設計與開發》 

當ActionServlet接收到一個客戶請求時,將執行如下流程: 

(1) 檢索和用戶請求匹配的ActionMapping實例,如果不存在,就返回用戶請求路徑無效的信息。 

(2) 如果ActionForm實例不存在,就創建一個ActionForm對象,把客戶提交的表單數據保存到ActionForm對象中。 

(3) 根據配置信息決定是否需要表單驗證。如果需要驗證,就調用ActionForm的validate()方法。 

(4) 如果ActionForm的validate()方法返回null返回一個不包含ActionMessage的ActionErrors對象,就表示表單驗證成功。 

(5) ActionServlet根據ActionMapping實例包含的映射信息決定將請求轉發給哪個Action。如果相應的Action實例不存在,就先創建這個實例,然後調用Action的execute()方法。 

(6) Action的execute()方法返回一個ActionForward對象,ActionServlet再把客戶請求轉發給ActionForward對象指向的JSP組件。 

(7) ActionForward對象指向的JSP組件生成動態網頁,返回給客戶。 

對於以上流程的流程(4),如果ActionForm的validate()方法返回一個包含一個或多個ActionMessage的ActionErrors對象,就表示表單驗證失敗,此時ActionServlet將直接把請求轉發給包含用戶提交表單的JSP組件。在這種情況下,不會再創建Action對象並調用Action的execute()方法。 
最後舊的談一談struts1與struts2的區別了: 

首先:struts1是通過servlet啓動的。 

一、struts1要求Action類繼承一個抽象基類,而不是接口。 

struts2的action類可以實現一個action接口,也可以實現其他接口。 



二、sturts1 action是單例模式,線程是不安全的。 

struts2 action線程是安全的,action爲每一個請求都生成了一個實例。 



三、sturts1過去依賴serlet API,不容易測試。 

struts2不依賴於容器,允許Action脫離容器單獨被測試。 



四、Struts1 使用ActionForm對象捕獲輸入。所有的ActionForm必須繼承一個基類。 

Struts 2直接使用Action屬性作爲輸入屬性,消除了對第二個輸入對象的需求。 



五、Struts1 整合了JSTL,因此使用JSTL EL。這種EL有基本對象圖遍歷,但是對集合和索引屬性的支持很弱。 

Struts2可以使用JSTL,但是也支持一個更強大和靈活的表達式語言--"Object Graph Notation Language" (OGNL). 



六、Struts 1使用標準JSP機制把對象綁定到頁面中來訪問。 

Struts 2 使用 "ValueStack"技術,使taglib能夠訪問值而不需要把你的頁面(view)和對象綁定起來。 



七、Struts 1 ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進行類型轉換。 

Struts2 使用OGNL進行類型轉換。提供基本和常用對象的轉換器。 



八、Struts 1支持在ActionForm的validate方法中手動校驗,或者通過Commons Validator的擴展來校驗。 

Struts2支持通過validate方法和XWork校驗框架來進行校驗。 



九、Struts1支持每一個模塊有單獨的Request Processors(生命週期),但是模塊中的所有Action必須共享相同的生命週期。 

Struts2支持通過攔截器堆棧(Interceptor Stacks)爲每一個Action創建不同的生命週期。堆棧能夠根據需要和不同的Action一起使用。http://www.linuxso.com/architecture/7694.html

十.執行流程 a)struts1  jsp發起httprequest請求->servlet捕獲->struts.xml->namespace+ActionName-> Action->填充表單setXxx()->action.execute()->”success”->Result->設置request屬性->跳轉目標頁

b) Action(jsp發起httprequest請求,被過濾器捕獲)->FilterDispatcher->struts.xml->namespace+ActionName->new Action->填充表單setXxx()->action.execute()->”success”->Result->設置request屬性->跳轉目標頁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章