Struts2--百度百科

Struts 2是Struts的下一代產品,是在 struts 1和WebWork的技術基礎上進行了合併的全新的Struts 2框架。其全新的Struts 2的 體系結構與Struts 1的體系結構差異巨大。Struts 2以WebWork爲核心,採用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器可以與 ServletAPI徹底脫離開,因此Struts 2能夠理解爲WebWork的更新產品。雖然從Struts 1到Struts 2有着太大的變化,可是相對於WebWork,Struts 2的變化很小。
外文名
Struts 2
解    釋
Struts的下一代產品
類    別
框架
理    解
WebWork的更新產品

發展歷史

編輯
通過六年多的發展,Struts1已經成爲了一個高度成熟的框架,無論是 穩定性仍是可靠性都獲得了普遍的證實。市場佔有率超過20%,擁有豐富的開發人羣,幾乎已經成爲了事實上的工業標準。可是隨着時間的流逝,技術的進 步,Struts1的侷限性也愈來愈多地暴露出來,而且制約了Struts1的繼續發展。
對於Struts1框架而言,因爲與JSP/Servlet耦合很是緊密,於是致使了一些嚴重的問題。首先,Struts1支持的表現層技術單一。因爲Struts1出現的年代比較早,那個時候沒有 FreeMarkerVelocity等技術,所以它不可能與這些視圖層的模版技術進行整合。其次,Struts1與Servlet API的嚴重耦合,使應用難於測試。最後,Struts1代碼嚴重依賴於Struts1 API,屬於侵入性框架。
從目前的技術層面上看,出現了許多與Struts1競爭的視圖層框架,好比 JSFTapestryspring MVC等。這些框架因爲出現的年代比較近,應用了最新的設計理念,同時也從Struts1中吸收了經驗,克服了不少不足。這些框架的出現也促進了Struts的發展。
Struts已經分化成了兩個框架:第一個是在傳統的Struts1的基礎上,融合了另外的一個優秀的Web框架 WebWork的Struts2。 Struts 2雖然是在Struts1的基礎上發展起來的,可是實質上是以WebWork爲核心的。Struts2爲傳統的Struts1注入了WebWork的先進的設計理念,統一了Struts1和WebWork兩個框架。
Struts1分化出來的另一個框架是 Shale。這個框架遠遠超出了Struts1原有的設計思想,與原有的Struts1關聯不多,使用了全新的設計思想。Shale更像一個新的框架而不是Struts1的升級。

工做原理

編輯
Struts 2的工做原理圖:
 
 

體系結構

編輯
應用流程註解
Web容器收到請求(HttpServletReques t)它將請求傳遞給一個標準的的過濾鏈包括(ActionContextCleanUp)過濾器。
通過Other filters(SiteMesh ,etc),須要調用FilterDispatcher核心控制器,而後它調用ActionMapper肯定請求哪一個 Action,ActionMapper返回一個收集Action詳細信息的ActionMaping對象。
FilterDispatcher將控制權委派給ActionProxy,ActionProxy調用配置管理器(ConfigurationManager) 從配置文件中讀取配置信息(struts.xml),而後建立ActionInvocation對象。
ActionInvocation在調用Action以前會依次的調用所 用配置攔截器(Interceptor N)一旦執行結果返回結果字符串ActionInvocation負責查找結果字符串對應的(Result)而後執行這個Result Result會調用一些模版(JSP)來呈現頁面。
攔截器(Interceptor N)會再被執行(順序和Action執行以前相反)最後響應(HttpServletResponse)被返回在web.xml中配置的那些過濾器和(核心控制器)(FilterDispatcher)。

技術改進

編輯
Struts 2對Struts1進行了巨大的改進。主要表如今以下幾個方面:
在Action的實現方面
Struts1要求必須統一擴展自Action類,而Struts2中能夠是一個 POJO
線程模型方面
Struts1的Action是單實例的,一個Action的實例處理全部的請求。Struts 2的Action是一個請求對應一個實例(每次請求時都新new出一個對象),沒有 線程安全方面的問題。
Servlet依賴方面
Struts1的Action依賴於Servlet API,好比Action的execute方法的參數就包括request和response對象。這使程序難於測試。Struts2中的Action再也不依賴於Servlet API,有利於測試,而且實現TDD。
封裝 請求參數
Struts1中強制使用ActionForm對象封裝請求的參數。Struts2能夠選擇使用POJO類來封裝請求的參數,或者直接使用Action的屬性。
表達式語言方面
Struts1中整合了EL,可是EL對集合和索引的支持不強,Struts2整合了 OGNL(Object Graph NavigationLanguage)。
綁定值到視圖技術
Struts1使用標準的JSP,Struts2使用「ValueStack」技術。
類型轉換
Struts1中的ActionForm基本使用String類型的屬性。Struts2中使用OGNL進行轉換,能夠更方便的使用。
Struts1中支持覆蓋validate方法或者使用Validator框架。Struts2支持重寫validate方法或者使用 XWork的驗證框架。
Action 執行控制 的對比
Struts1支持每個模塊對應一個請求處理,可是模塊中的全部Action必須共享相同的生命週期。Struts2支持經過攔截器 堆棧爲每個Action建立不一樣的生命週期。
攔截器的應用
攔截器,在AOP(Aspect-Oriented Programming)中用於在某個方法或字段被訪問以前,進行攔截而後在以前或以後加入某些操做。攔截是AOP的一種實現策略。
在Webwork的中文文檔的解釋爲——攔截器是動態攔截Action調用的對象。它提供了一種機制可使開發者能夠定義在一個action執行的先後執行的代碼,也能夠在一個action執行前阻止其執行。同時也是提供了一種能夠提取action中可重用的部分的方式。
談到攔截器,還有一個詞你們應該知道——攔截器鏈 (Interceptor Chain,在Struts 2中稱爲攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用。
1.攔截器的實現原理:
大部分時候,攔截器方法都是經過代理的方式來調用的。Struts 2的攔截器實現相對簡單。當請求到達Struts 2的ServletDispatcher時,Struts 2會查找配置文件,並根據其配置實例化相對的攔截器對象,而後串成一個列表(list),最後一個一個地調用列表中的攔截器。
2.攔截器的配置
Struts 2已經爲您提供豐富多樣的,功能齊全的攔截器實現。你們能夠至struts2的jar包內的struts-default.xml查看關於默認的攔截器與攔截器鏈的配置。
在struts.xml文件中定義攔截器,攔截器棧:
1
2
3
4
5
6
7
8
9
10
11
12
< package  name= "my"  extends = "struts-default"  namespace= "/manage" >
<interceptors>
<!-- 定義攔截器 -->
<interceptor name= "攔截器名"  class = "攔截器實現類" />
<!-- 定義攔截器棧 -->
<interceptor-stack name= "攔截器棧名" >
<interceptor-ref name= "攔截器一" />
<interceptor-ref name= "攔截器二" />
</interceptor-stack>
</interceptors>
......
</ package >

對比

編輯
Struts和Webwork同爲服務於Web的一種MVC框架,從某種 程度上看,Struts2是從WebWork2上升級獲得的。甚至Apache的官方文檔也講:WebWork2到Struts2是平滑的過渡。咱們甚至 也能夠說Struts2就是WebWork2.3而已。在不少方面Struts僅僅是改變了WebWork下的名稱。Struts2對應的有本身的標籤, 而且功能強大。Webwork也有本身的標籤。在2005年12月,WebWork與Struts Ti決定合併, 在此同時, Struts Ti 更名爲 Struts Action Framework 2.0,成爲Struts真正的下一代。

基類

編輯

標準返回值

ActionSupport基類中定義了五個標準的返回值 ,固然咱們能夠本身隨意定義返回的名字
String SUCCESS = "success"; //默認是 SUCCESS 類型
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";

方法

ActionSupport基類定義了了一些方法,程序員本身寫的action若是繼承了ActionSupport基類,就能夠應用這些方法,很方便解決一些問題。
一些比較經常使用的方法:
getText(String aTextName);//國際化用到
...//getText(String aTextName)的 重載方法
addActionMessage(String aMessage);
addFieldError(String fieldName, String errorMessage);
//校驗失敗後返回給客戶端的信息,struts2 標籤<s:fielderror />能夠取得
addActionError(String anErrorMessage);

Result Type

編輯
在默認時,<result>標籤的type屬性值是「dispatcher」(實際上就是轉發,forward)。開發人員能夠根據本身的須要指定不一樣的類型,如redirect、stream等。以下面代碼所示:
<result name="save" type="redirect">
/result.jsp
</result>
這此result-type能夠在struts2-core-2.0.11.1.jar包或struts2 源代碼中的struts-default.xml文件中找到,在這個文件中找到<result-types>標籤,全部的result-type都在裏面定義了。代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<result-types>
<result-type name= "chain"  class = "com.opensymphony.xwork2.ActionChainResult" />
<result-type name= "dispatcher"  class = "org.apache.struts2.dispatcher.ServletDispatcherResult"  default = "true" />
<result-type name= "freemarker"  class = "org.apache.struts2.views.freemarker.FreemarkerResult" />
<result-type name= "httpheader"  class = "org.apache.struts2.dispatcher.HttpHeaderResult" />
<result-type name= "redirect"  class = "org.apache.struts2.dispatcher.ServletRedirectResult" />
<result-type name= "redirectAction"  class = "org.apache.struts2.dispatcher.ServletActionRedirectResult" />
<result-type name= "stream"  class = "org.apache.struts2.dispatcher.StreamResult" />
<result-type name= "velocity"  class = "org.apache.struts2.dispatcher.VelocityResult" />
<result-type name= "xslt"  class = "org.apache.struts2.views.xslt.XSLTResult" />
<result-type name= "plainText"  class = "org.apache.struts2.dispatcher.PlainTextResult"  />
<!-- Deprecated name form scheduled  for  removal in Struts  2.1 . 0 . The camelCase versions are preferred. See ww- 1707  -->
<result-type name= "redirect-action"  class = "org.apache.struts2.dispatcher.ServletActionRedirectResult" />
<result-type name= "plaintext"  class = "org.apache.struts2.dispatcher.PlainTextResult"  />
</result-types>

dispatcher

用來轉向頁面,一般處理JSP
1
org.apache.struts2.dispatcher.ServletDispatcherResult

freemaker

處理FreeMarker模板
1
org.apache.struts2.views.freemarker.FreemarkerResult

httpheader

控制特殊HTTP行爲的結果類型
1
org.apache.struts2.dispatcher.HttpHeaderResult

stream

向瀏覽器發送InputStream對象,一般用來處理文件下載,還可用於返回AJAX數據
1
org.apache.struts2.dispatcher.StreamResult
StreamResult等價於在Servlet中直接輸出Stream流。這種Result被常用於輸出圖片、文檔等二進制流到 客戶端。經過使用StreamResult,咱們只須要在Action中準備好須要輸出的InputStream便可。
配置:
1
2
3
4
5
6
<result name= "success"  type= "stream" >
<param name= "contentType" >image/jpeg</param>
<param name= "inputName" >imageStream</param>
<param name= "contentDisposition" >filename= "document.pdf" </param>
<param name= "bufferSize" > 1024 </param>
</result>
同時,StreamResult支持許多參數,對輸出的Stream流進行參數控制。

velocity

處理Velocity模板
1
org.apache.struts2.dispatcher.VelocityResult
隨 着模板技術的愈來愈流行,使用Freemarker或者Velocity模板進行View層展現的開發者愈來愈多。Struts2一樣爲模板做爲 Result作出了支持。因爲模板的顯示須要模板(Template)與數據(Model)的緊密配合,因此在Struts2中,這兩個Result的主 要工做是爲模板準備數據。

xslt

處理XML/XLST模板
1
org.apache.struts2.views.xslt.XSLTResult

plainText

顯示原始文件內容,例如文件源代碼
1
org.apache.struts2.dispatcher.PlainTextResult

chain

用來處理Action鏈
1
com.opensymphony.xwork2.ActionChainResult
chain 其實只是在一個action執行完畢以後,forward到另一個action,因此他們之間是共享HttpServletRequest的。在使用 chain做爲Result時,每每會配合使用ChainingInterceptor。ChainingInterceptor的做用是在Action 直接傳遞數據。事實上,源Action中ValueStack的數據會被作一次Copy,這樣,2個Action中的數據都在ValueStack中,使 得對於前臺來講,經過ValueStack來取數據,是透明而共享的。好比說,一張頁面中,你可能有許多數據要顯示,而某些數據的獲取方式可能被不少不一樣 的頁面共享(典型來講,「推薦文章」這個小欄目的數據獲取,可能會被不少頁面所共享)。這種狀況下,能夠把這部分邏輯抽取到一個獨立Action中,並使 用chain,將這個Action與主Action串聯起來。這樣,最後到達頁面的時候,頁面始終能夠獲得每一個Action中的數據。
從實戰上講,使用chain做爲Result也的確存在着上面所說的許多 問題,我我的也是很是不推崇濫用這種Result。尤爲是,對於使用Spring和Hibernate的朋友來講,若是你開啓 OpenSessionInView模式,那麼Hibernate的session是跟隨HttpServletRequest的,因此session在 整個action鏈中共享。這會爲咱們的編程帶來極大的麻煩。由於咱們知道Hibernate的session會保留一份一級緩存,在action鏈中, 共享一級緩存無疑會爲你的調試工做帶來很大的不方便。
因此,謹慎使用chain做爲你的Result,應該成爲一條最佳實踐。

redirect

重定向到一個URL
1
org.apache.struts2.dispatcher.ServletRedirectResult
如 果你在Action執行完畢後,但願執行另外一個Action,有2種方式可供選擇。一種是forward,另一種是redirect。有關 forward和redirect的區別,這裏我就再也不展開,這應該屬於Java程序員的基本知識。在Struts2中,分別對應這兩種方式的 Result,就是chain和redirect。
先來談談redirect,既然是重定向,那麼源地址與目標地址之間是2個不一樣的HttpServletRequest。因此目標地址將沒法經過ValueStack等Struts2的特性來獲取源Action中的數據。
同時,Redirect的Result支持在配置文件中,讀取並解析源Action中ValueStack的值,併成爲 參數傳遞到Redirect的地址中。

redirectAction

重定向到一個Action
1
org.apache.struts2.dispatcher.ServletActionRedirectResult

區別比較

編輯
redirect和redirectAction chain的區別
struts2中關於result的返回類型通常咱們是轉發到一個jsp 頁面或者是html頁面等,可是struts2中的result的返回類型還有redirect,redirectAction,chain。對於這三種 返回類型之間確定是有區別的,下面咱們來看看關於redirect redirectAction chain這三種struts2的返回類型之間的區別。當使用type=「redirectAction」 或type=「redirect」提交到一個action而且須要傳遞一個參數時。這裏是有區別的:使用type=「redirectAction」時, 結果就只能寫Action的配置名,不能帶有後綴:「.action」
Xml代碼
1
2
3
<action name= "Login"  class = "steven.actions.LoginAction" >
<result name= "success"  type= "redirectAction" >User?u_id=${loginBean.u_id}</result>
</action>
使用type=「redirect」時,結果應是action配置名+後綴名
Xml代碼
1
2
3
<action name= "Login"  class = "steven.actions.LoginAction" >
<result name= "success"  type= "redirect" >User.action?u_id=${loginBean.u_id}</result>
</action>
redirect:action處理完後重定向到一個視圖資源(如:jsp頁面),請求參數所有丟失,action處理結果也所有丟失。
redirect-action:action處理完後重定向到一個action,請求參數所有丟失,action處理結果也所有丟失。
chain:action處理完後轉發到一個action,請求參數所有丟失,action處理結果不會丟失。

出現漏洞

編輯
曝出高危安全漏洞
Struts2曝出2個高危 安全漏洞,一個是使用縮寫的導航參數前綴時的遠程代碼執行漏洞,另外一個是使用縮寫的重定向參數前綴時的開放式重定向漏洞。這些漏洞可以使黑客取得網站服務器的「最高權限」,從而使企業服務器變成黑客手中的「肉雞」。
解決措施
Apache Struts團隊已發佈了最新的Struts 2.3.15.1,修復了上述漏洞,建議採用Struts 2.0至Struts 2.3的網站開發者儘快升級至最新版。 [1]  
帶來影響
據烏雲平臺漏洞報告,淘寶、京東、騰訊等大型互聯網廠商均受此影響,並且 漏洞利用代碼已經被強化,可直接經過瀏覽器的提交對服務器進行任意操做並獲取敏感內容。Struts漏洞影響巨大,受影響站點以電商、銀行、門戶、政府居 多,並且一些自動化、傻瓜化的利用工具開始出現,填入地址可直接執行服務器命令,讀取數據甚至直接關機等操做。 [1]  
瑞星安全專家介紹,本次曝出的2個漏洞是因爲縮寫的導航和重定向前綴 「action:」、 「redirect:」、 「redirectAction:」形成的。瑞星安全專家表示,因爲這些參數前綴的內容沒有被正確過濾,致使黑客能夠經過漏洞執行命令,獲取目標服務器的 信息,並進一步取得服務器最高控制權。屆時,被攻擊網站的數據庫將面臨全面泄密的威脅,同時黑客還能夠經過重定向漏洞的手段,對其餘網民進行 釣魚攻擊掛馬 攻擊[2]  
相關文章
相關標籤/搜索