Struts2工作原理(圖解)
寫在前面:Struts2主要包含前端控制器FC、Action、ValueStack容器、Result、Interceptor攔截器、Tags標籤6個核心元件,本文主要介紹這幾個元件的合作關係,由此構成Struts2的工作流程,以便更好地理解和使用Struts2。
背景知識
1、Struts2基礎標籤
1)用於輸出的標籤
--*<s:property value="name"/> value的值實際上是OGNL表示式
--特殊用法
<s:property /> 用於輸出棧頂資料
2)用於除錯的標籤
<s:debug/>
--該標籤僅僅是給程式設計師用的,用於除錯,即用於觀察ValueStack中的資料
--當程式碼提交給測試、客戶時,要把該標籤刪除
--該標籤具有互斥性(可以理解為BUG),如果頁面上出現多次這個標籤時,實際上只有第一個有效
3)用於迴圈的標籤
a、用於迴圈集合
--比如Action中有集合屬性List<User> users
<s:iterator value="users">
<s:property value="userName"/>
</s:iterator>
b、用於迴圈數字
<s:iterator begin="1" end="3" var="i">
<s:property value="#i"/>
</s:iterator>
2、OGNL表示式
1)類似於EL表示式,但是比EL功能強大
2)表示式允許我們通過一個字串,來訪問JAVA物件。從而避免了在JSP上巢狀著寫JAVA程式碼。即,表示式可以通過字串間接的幫助我們訪問JAVA物件。
3)基本原理
--OGNL表示式將被OGNL引擎解析,這個過程是Struts2自行完成的
--OGNL引擎允許我們訪問兩種型別的物件,一種是JavaBean型別,稱之為root物件;另一種為Map型別,稱之為context物件。
--當OGNL表示式以#開頭時,OGNL引擎會訪問context物件,否則會訪問root物件
4)root物件
--我們寫OGNL表示式時(不以#開頭的情況),首先要明確誰是root物件,其次從該物件的下級屬性寫起。
舉例:
--比如以Action為root物件,Action中有String name, User user屬性,那麼要在頁面顯示這兩個屬性的話,寫法如下:
<s:property value="name"/>
<s:property value="user.userName"/>
--比如以User為root物件,要在頁面上顯示它的名稱,寫法如下:
<s:property value="userName"/>
5)context物件
--OGNL表示式以#開頭,則訪問context物件
--#後面寫的是context物件的key,context物件是Map型別
3、ValueStack
1)什麼是ValueStack
Struts2中並不是直接將OGNL元件搬過來使用,而是使用一個物件容器ValueStack對這個元件進行了改造及封裝,因此我們在Struts2中是通過ValueStack來使用OGNL表示式。並且ValueStack中封裝了Action的資料,上下文等資料,這些資料我們都可以通過OGNL表示式來獲得。
2)原理
--結構:ValueStack中封裝了OGNL引擎、context物件、Stack物件。
--規則:當我們在標籤中寫一個OGNL表示式時,該表示式被Struts2自動的傳遞給ValueStack中的OGNL引擎,引擎會判斷表示式是否以#開頭,若是則直接從context物件中取值,否則向Stack中取值。
--如何向Stack取值:OGNL表示式從棧頂向下依次取值,它是以棧的每一級物件作為root物件從中取值的,若取到值則直接返回,否則繼續向下取值,直到棧底為止。
3)*棧頂的變化
a、預設情況下,棧頂是Action
*b、在迴圈時,棧頂將發生變化,規則如下:
--在未迴圈時,棧頂依然是Action
--在第一次迴圈時,Struts2將迴圈變數(如user)壓入到棧中,因此迴圈變數佔據棧頂位置,而Action處於棧的第二位。
--在第n次迴圈時,Struts2將第n-1次的迴圈變數從棧頂移除,然後再將本次迴圈的變數壓入棧中,因此本次迴圈的變數佔據棧頂位置,而Action依然處於棧的第二位。
--當最後一次迴圈結束時,Struts2將最後一次迴圈的變數從棧頂移除,而沒有新的變數壓入棧中,那麼Action再次成為棧頂。
簡而言之:
--在迴圈過程中,棧頂是迴圈變數
--迴圈結束後,棧頂是Action
4)*總結(OGNL,ValueStack)
a、在沒有迴圈時,棧頂是Action,即可以以Action為root來寫OGNL表示式
b、在迴圈時,棧頂是迴圈變數,棧第二位是Action
--迴圈集合
棧頂是集合中的物件,那麼可以以該物件為root,來寫OGNL表示式,即直接從該root物件的下級屬性寫起
舉例:Action中有屬性List<User> users,在頁面上迴圈users
<s:iterator value="users">
<s:property value="userName"/>
</s:iterator>
即:迴圈過程中,棧頂是User物件,以它為root來寫OGNL表示式的話,就寫userName
--迴圈數字
棧頂是迴圈變數(數字),但是由於我們不能以數字為root(以JavaBean為root)來寫OGNL表示式,因為數字已經是基本型別資料,沒有下級屬性讓我們訪問。如果我們想直接輸出棧頂可以用<s:property/>,如果我們想引用迴圈變數,則需要寫<s:property value="#i"/>,從context物件中依然可以取得這個值。
舉例:從1迴圈到3
<s:iterator begin="1" end="3" var="i">
<s:property value="#i"/>
</s:iterator>
工作原理
總結8句話,方便記憶:
請求提交控制器,根據配置找Action。建立VS棧容器,例項Action放棧頂。
呼叫Action算輸出,歷經層層攔截器。根據方法返回值,呼叫Result做輸出。
詳細流程如下(結合圖示理解):
1、請求傳入前端控制器FC
2、前端控制器FC根據Struts.xml配置檔案查詢Action
3、建立ValueStack值棧容器
4、建立Action並存入ValueStack棧頂
5、6、7、FC呼叫並執行Action邏輯,此過程可能先被Interceptor攔截器攔截處理
8、9、FC根據Action返回的result通過Result元件跳轉到相應的JSP介面
10、在解析JSP時,若發現OGNL表示式,則向ValueStack容器中的OGNL引擎傳入表示式,按照先前介紹的方式查詢對應的值
11、OGNL引擎返回查詢到的值給JSP,待所有資料載入完成,呈現JSP(通過Tags標籤)介面
Tips:當重新提交請求(比如重新整理介面)時,Action、ValueStack均會被重新建立。
原文:https://blog.csdn.net/daijin888888/article/details/51461043?utm_source=copy
相關文章
- Struts2 原始碼分析-----工作原理分析原始碼
- struts2的工作原理與檔案結構
- 圖解WebGL和Three.js工作原理圖解WebJS
- 圖文詳解 HDFS 的工作機制及其原理
- 圖解通訊原理(乙太網通訊及物理層工作原理)圖解
- SpringMVC工作原理詳解SpringMVC
- RabbitMQ原理和架構圖解(附6大工作模式)MQ架構圖解模式
- GPIO口工作原理的超詳細解釋(附電路圖)
- 點陣圖索引的工作原理 - Richard索引
- JUnit 註解@RunWith的工作原理
- JUnit 註解@Category的工作原理Go
- JUnit 註解@SuiteClasses的工作原理UI
- JUnit 註解@Rule的工作原理
- Keepalived高可用叢集工作原理示意圖
- 瞭解ansible架構與工作原理架構
- Semaphore 使用&核心原理 圖解圖解
- 深度圖解Redis Cluster原理圖解Redis
- Spring框架裡註解@Autowired的工作原理Spring框架
- XtraBackup工具詳解 Part 3 XtraBackup工作原理
- Angular @Injectable 註解的工作原理淺析Angular
- 代理伺服器的工作原理詳解伺服器
- 用三張圖理解深度學習的工作原理深度學習
- 圖解Go select語句原理圖解Go
- 清晰圖解深度分析HTTPS原理圖解HTTP
- Java JUnit框架裡@Category註解的工作原理Java框架Go
- KubernetesAPIserver工作原理APIServer
- Mybatis工作原理MyBatis
- require工作原理UI
- HTTPS工作原理HTTP
- Nginx工作原理Nginx
- pr工作原理
- SpringMVC工作原理SpringMVC
- 【struts2】
- 圖解Java執行緒池原理圖解Java執行緒
- 圖解Flutter——BLoC的原理及使用圖解FlutterBloC
- 圖解Go的channel底層原理圖解Go
- 圖解MongoDB叢集部署原理(3)圖解MongoDB
- 交換機的作用、功能和工作原理詳解