Struts2 學習 Struts2
Struts2
一、Struts2簡介
1.概念:輕量級的MVC框架,主要解決了請求分發的問題,重心在控制層和表現層。低侵入性,與業務程式碼的耦合度很低。Struts2實現了MVC,並提供了一系列API,採用模式化方式簡化業務開發過程。
2.與Servlet對比
優點:業務程式碼解耦,提高開發效率
缺點:執行效率偏低,需要使用反射、解析XML等技術手段,結構複雜
3.不同框架實現MVC的方式
Servlet:
Spring:
Struts2:
二、Struts2使用
1.使用步驟
匯入Struts2核心jar包
在web.xml配置前端控制器filter
<filter> <filter-name>Struts2</fileter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> <filter-mapping>
建立struts.xml(格式可以參考核心包根路徑下的DTD檔案,struts-default.xml)
編寫控制器Action
- 方法是public的
- 返回值為String型別(返回值與struts.xml->action->result的name屬性匹配,即根據此返回值找到對應result)
- 引數列表為空
建立JSP頁面
配置struts.xml
<struts>
<!-- i18n:國際化,解決post亂碼問題 -->
<constant name="struts.i18n.encoding" value="=UTF-8"></constant>
<!-- 指定範文action的字尾名;如果不設定可以直接訪或者直接訪問路徑.action,兩個逗號表示可以為空,預設為action,如果設定則必須加.value(設定的值) -->
<constant name="struts.action.extension" value="=action,,"></constant>
<!-- 模式配置是false,如果改為true;
表示開發模式 1、熱載入主配置(只對struts配置生效)不需要重啟即可生效
2、可以提供更多的錯誤輸出,方便開發時的除錯 -->
<constant name="struts.devMode" value="=false">
</constant>
<!--
package:包,用於對Action進行封裝 name:包名,根元素下可以有多個包,彼此不能重名 extends:繼承,用於指定繼承的包,相當於將繼承包下的配置資訊複製到當前包 namespace:名稱空間,用於規定Action的訪問路徑,必須“/”開頭 --> <package name="test01" namespace="/test01" extends="struts-default"> <!--action:業務控制器,用於註冊業務控制器元件 name:action名稱,用於規定Action的訪問路徑 class:業務控制器元件,用於指定業務控制器對應的類 method:方法,用於指定訪問當前action時要呼叫的方法 *請求URL:http://ip:port/projectName/namespace/ActionName.action --> <action name="hello" class="test01.konrad.action.HelloAction" method="execute"> <!--result:輸出元件,用於轉發、重定向、直接輸出 name:名稱,一個action下可以有多個result,彼此不能重名 預設值轉發,元素內設定轉發的頁面 --> <result name="success">/hello.jsp</result> </action> </package> </struts>
三、引數傳遞
1.Action從頁面取值
a)基本屬性注入(頁面,Action)
b)域模型注入(頁面,Action)
2.頁面從Action取值
a)使用EL表示式
b)OGNL
四、OGNL
1.概念:Object Graph Navigation Language,是一門功能強大的表示式語言,類似於EL。Strut2預設採用OGNL表示式訪問Action的資料,實際上是通過ValueStack物件來訪問Action。
2.用法:在Struts2中,OGNL表示式要結合Struts2標籤來訪問資料
EL:${user.userName} <==> OGNL:<s:property value="user.userName">
*a)訪問基本屬性 <s:property value="屬性名"/>
*b)訪問實體物件 <s:property value="物件名.屬性名"/>
c)訪問陣列/集合 <s:property value="someArray[1]"/> | <s:property value="someList[1]"/>
d)訪問Map <s:property value="someMap.key" />
e)運算 <s:property value="'My name is' + name" />
f)呼叫方法 <s:property value="name.toUpperCase()" />
g)建立集合 <s:property value="{'a','b','c'}" /> ArrayList
h)建立Map <s:property value="#{'mm':'MM','nn':'NN'}" /> LinkedHashMap
五、ValueStack
1.概念:是Struts2中,Action向頁面傳遞資料的媒介,封裝了Action的資料,並允許JSP通過OGNL來對其訪問
2.原理
3.訪問ValueStack
a)通過<s:debug>觀察其結構
b)輸出棧頂:<s:property />
c)訪問Context物件:
- OGNL表示式以"#"開頭
- 以key來訪問context物件的值,即"#key"得到context中某屬性值
d)迭代集合
e)按數字迭代
4.ValueStack棧頂的變化
- 預設情況下棧頂為Action
- 迴圈過程中,棧頂為迴圈變數(集合迭代時,迴圈變數是集合中的物件,即棧頂為實體物件,可以以實體物件為root來寫OGNL表示式;數字迭代時,迴圈變數是數字,不能以數字為實體物件,需要通過var宣告變數名,以"#變數名"來引用,此情況下,是從context物件中取出值)
- 迴圈結束後,棧頂變回Action
5.EL表示式訪問ValueStack
a)EL也是從ValueStack中取的值
b)EL預設的取值範圍是page,request,session,application
c)Struts2重寫的request的getAttribute方法,先試圖從原始request中取值,如果沒取到再從ValueStack中取值
六、Action基本原理
1.6大核心元件
FC:前端控制器,負責統一的分發請求
Action:業務控制器,負責處理某一類業務
ValueStack:Action與JSP資料互動的媒介
Interceptor:攔截器,負責擴充套件Action,處理Action的共通事務
Result:負責輸出的元件
Tags:標籤,負責顯示資料、生成框體
2.獲取Session的方式
a)ActionContext
- ActionContext.getContext().getSesion(),返回Map<String, Object>
b)ServletActionContext
- ServletActionContext.getRequest().getSession(),返回HttpSession
c)SessionAware(推薦使用)
- 讓Action實現SessionAware介面
- 實現setSession(Map<String, Object> session)方法,Struts2會在例項化Action後呼叫方法,通過方法引數將Session物件注入進來
- 定義成員變數,接收注入進來的Session物件
七、Result原理
1.介紹:用於做輸出的元件,用於向頁面輸出一些內容,轉發、重定向可以理解為特殊方式的輸出。每一個Result實際上是一個類,這些類都實現了共同的介面Result。Struts2預置了10種類型的Result,定義在strtus-default.xml
2.Result型別
a)dispatcher:用於轉發的result,可以將請求轉發給JSP,這種型別的Result對應的類為ServletDispacherResult,通過default="true"指定該Result為Struts2預設的Result型別。
b)stream:用於向頁面輸出二進位制資料,此種類型的Result可以將二進位制資料輸出到請求發起端,對應類為StreamResult
<result name="success" type="stream">
<!--codeStream 為定義在Action的輸入流InputStream --> <param name="inputName">codeStream</param> </result>
c)redirectAction:用於將請求重定向給另外一個Action,對應類為ServletActionRedirectResult
<result name="login" type="redirectAction"> <!--若重定向的Action與當前Action在同一個namespace下,可以省略namespace--> <param name="namespace"> /名稱空間 </param> <param name="actionName"> action名 </param> </result>
d)json:用於向頁面輸出json格式的資料,可以將json字串輸出到請求發起端。對應類為JSONResult
<result name="success" type="json"> <!--輸出一個Action屬性 指定屬性為基本型別,則直接返回該屬性值 如果指定屬性為實體物件,則返回格式{"code":"as1","name":"hk"} --> <param name="root">屬性名</param> <!--輸出多個Action屬性--> <param name="includeProperties">屬性名1,屬性名2...</param> <!--輸出所有屬性,不需要param標籤--> </result>
json需要導包,修改package繼承關係為json-default
八、UI標籤
1.表單 <s:form action="" method="" theme="simple" ></s:form>
2.文字框 <s:textfield name="userName" />
3.布林框 <s:checkbox name="marry" />
4.單選框 <s:radio name="sex" list="#{'M':'男','F':'女'}"/> 靜態初始化
<s:radio name="favoriteCities" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
5.多選框 <s:checkboxlist name="travelCities" list="#{'01':'北京','02':'上海','03':'廣州'}" /> 靜態初始化
<s:checkboxlist name="travelCities" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
6.下拉選 <s:select name="home" list="#{'01':'北京','02':'上海','03':'廣州'}" /> 靜態初始化
<s:select name="home" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
九、攔截器
1.用途:攔截器適合封裝一些通用處理,便於重複利用。例如請求引數傳遞給Action屬性,日誌的記錄,許可權檢查,事務處理等。攔截器是通過配置方式呼叫,因此使用方法比較靈活,便於維護和擴充套件。
2.使用步驟
建立攔截器元件(建立一個類,實現Interceptor介面,並實現intercept方法;也可以繼承MethodFilterInterceptor,這種方式可以使action中某個方法不進行攔截)
public String intercept(ActionInvocation invocation){ //攔截器--前部分處理 invocation.invoke(); //攔截器--後續處理 }
註冊攔截器
<package> <interceptors> <interceptor name="別名" class="實現類"/> <!--其他攔截器--> </interceptors> </package>
引用攔截器(哪個Action希望被攔截器擴充套件,需要在此action配置下,引用攔截器)
<action>
<!--手動的使用一次系統預設的攔截器-->
<interceptor-ref name="defaultStack"/> <interceptor-ref name="攔截器別名"/> <!--可以寫多個-->
<!--可以使用excludeMethods引數屬性,設定不過濾的方法--> </action>
3.攔截器棧
<interceptor-stack name="myStack"> <interceptor-ref name="攔截器別名1"/> <interceptor-ref name="攔截器別名2"/> </interceptor-stack>
4.FileUpload攔截器
a)原理:首先FileUpload攔截器將表單中提交的檔案,以臨時檔案的形式儲存到伺服器臨時路徑下。之後FileUpload攔截器將該臨時檔案物件注入給Action,Action自主處理該臨時檔案。最後FileUpload攔截器刪除臨時檔案。
b)使用步驟
導包 commons-io.jar
Action:定義File型別屬性(如some),接受攔截器注入的臨時檔案物件。若想要獲取原始檔名,要定義String型別屬性,屬性名為File型別屬性+FileName(如someFileName)
表單設定:method="post", enctype="multipart/form-data"
c)設定限制(Struts2檔案上傳預設最大值為2097152B,即2M)
在struts.xml中重置預設限制值 <constant name="struts.multipart.maxSize" value="5000000" />
一、Struts2簡介
1.概念:輕量級的MVC框架,主要解決了請求分發的問題,重心在控制層和表現層。低侵入性,與業務程式碼的耦合度很低。Struts2實現了MVC,並提供了一系列API,採用模式化方式簡化業務開發過程。
2.與Servlet對比
優點:業務程式碼解耦,提高開發效率
缺點:執行效率偏低,需要使用反射、解析XML等技術手段,結構複雜
3.不同框架實現MVC的方式
Servlet:
Spring:
Struts2:
二、Struts2使用
1.使用步驟
匯入Struts2核心jar包
在web.xml配置前端控制器filter
<filter> <filter-name>Struts2</fileter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> <filter-mapping>
建立struts.xml(格式可以參考核心包根路徑下的DTD檔案,struts-default.xml)
編寫控制器Action
- 方法是public的
- 返回值為String型別(返回值與struts.xml->action->result的name屬性匹配,即根據此返回值找到對應result)
- 引數列表為空
建立JSP頁面
配置struts.xml
<struts>
<!-- i18n:國際化,解決post亂碼問題 -->
<constant name="struts.i18n.encoding" value="=UTF-8"></constant>
<!-- 指定範文action的字尾名;如果不設定可以直接訪或者直接訪問路徑.action,兩個逗號表示可以為空,預設為action,如果設定則必須加.value(設定的值) -->
<constant name="struts.action.extension" value="=action,,"></constant>
<!-- 模式配置是false,如果改為true;
表示開發模式 1、熱載入主配置(只對struts配置生效)不需要重啟即可生效
2、可以提供更多的錯誤輸出,方便開發時的除錯 -->
<constant name="struts.devMode" value="=false">
</constant>
<!--
package:包,用於對Action進行封裝 name:包名,根元素下可以有多個包,彼此不能重名 extends:繼承,用於指定繼承的包,相當於將繼承包下的配置資訊複製到當前包 namespace:名稱空間,用於規定Action的訪問路徑,必須“/”開頭 --> <package name="test01" namespace="/test01" extends="struts-default"> <!--action:業務控制器,用於註冊業務控制器元件 name:action名稱,用於規定Action的訪問路徑 class:業務控制器元件,用於指定業務控制器對應的類 method:方法,用於指定訪問當前action時要呼叫的方法 *請求URL:http://ip:port/projectName/namespace/ActionName.action --> <action name="hello" class="test01.konrad.action.HelloAction" method="execute"> <!--result:輸出元件,用於轉發、重定向、直接輸出 name:名稱,一個action下可以有多個result,彼此不能重名 預設值轉發,元素內設定轉發的頁面 --> <result name="success">/hello.jsp</result> </action> </package> </struts>
三、引數傳遞
1.Action從頁面取值
a)基本屬性注入(頁面,Action)
b)域模型注入(頁面,Action)
2.頁面從Action取值
a)使用EL表示式
b)OGNL
四、OGNL
1.概念:Object Graph Navigation Language,是一門功能強大的表示式語言,類似於EL。Strut2預設採用OGNL表示式訪問Action的資料,實際上是通過ValueStack物件來訪問Action。
2.用法:在Struts2中,OGNL表示式要結合Struts2標籤來訪問資料
EL:${user.userName} <==> OGNL:<s:property value="user.userName">
*a)訪問基本屬性 <s:property value="屬性名"/>
*b)訪問實體物件 <s:property value="物件名.屬性名"/>
c)訪問陣列/集合 <s:property value="someArray[1]"/> | <s:property value="someList[1]"/>
d)訪問Map <s:property value="someMap.key" />
e)運算 <s:property value="'My name is' + name" />
f)呼叫方法 <s:property value="name.toUpperCase()" />
g)建立集合 <s:property value="{'a','b','c'}" /> ArrayList
h)建立Map <s:property value="#{'mm':'MM','nn':'NN'}" /> LinkedHashMap
五、ValueStack
1.概念:是Struts2中,Action向頁面傳遞資料的媒介,封裝了Action的資料,並允許JSP通過OGNL來對其訪問
2.原理
3.訪問ValueStack
a)通過<s:debug>觀察其結構
b)輸出棧頂:<s:property />
c)訪問Context物件:
- OGNL表示式以"#"開頭
- 以key來訪問context物件的值,即"#key"得到context中某屬性值
d)迭代集合
e)按數字迭代
4.ValueStack棧頂的變化
- 預設情況下棧頂為Action
- 迴圈過程中,棧頂為迴圈變數(集合迭代時,迴圈變數是集合中的物件,即棧頂為實體物件,可以以實體物件為root來寫OGNL表示式;數字迭代時,迴圈變數是數字,不能以數字為實體物件,需要通過var宣告變數名,以"#變數名"來引用,此情況下,是從context物件中取出值)
- 迴圈結束後,棧頂變回Action
5.EL表示式訪問ValueStack
a)EL也是從ValueStack中取的值
b)EL預設的取值範圍是page,request,session,application
c)Struts2重寫的request的getAttribute方法,先試圖從原始request中取值,如果沒取到再從ValueStack中取值
六、Action基本原理
1.6大核心元件
FC:前端控制器,負責統一的分發請求
Action:業務控制器,負責處理某一類業務
ValueStack:Action與JSP資料互動的媒介
Interceptor:攔截器,負責擴充套件Action,處理Action的共通事務
Result:負責輸出的元件
Tags:標籤,負責顯示資料、生成框體
2.獲取Session的方式
a)ActionContext
- ActionContext.getContext().getSesion(),返回Map<String, Object>
b)ServletActionContext
- ServletActionContext.getRequest().getSession(),返回HttpSession
c)SessionAware(推薦使用)
- 讓Action實現SessionAware介面
- 實現setSession(Map<String, Object> session)方法,Struts2會在例項化Action後呼叫方法,通過方法引數將Session物件注入進來
- 定義成員變數,接收注入進來的Session物件
七、Result原理
1.介紹:用於做輸出的元件,用於向頁面輸出一些內容,轉發、重定向可以理解為特殊方式的輸出。每一個Result實際上是一個類,這些類都實現了共同的介面Result。Struts2預置了10種類型的Result,定義在strtus-default.xml
2.Result型別
a)dispatcher:用於轉發的result,可以將請求轉發給JSP,這種型別的Result對應的類為ServletDispacherResult,通過default="true"指定該Result為Struts2預設的Result型別。
b)stream:用於向頁面輸出二進位制資料,此種類型的Result可以將二進位制資料輸出到請求發起端,對應類為StreamResult
<result name="success" type="stream">
<!--codeStream 為定義在Action的輸入流InputStream --> <param name="inputName">codeStream</param> </result>
c)redirectAction:用於將請求重定向給另外一個Action,對應類為ServletActionRedirectResult
<result name="login" type="redirectAction"> <!--若重定向的Action與當前Action在同一個namespace下,可以省略namespace--> <param name="namespace"> /名稱空間 </param> <param name="actionName"> action名 </param> </result>
d)json:用於向頁面輸出json格式的資料,可以將json字串輸出到請求發起端。對應類為JSONResult
<result name="success" type="json"> <!--輸出一個Action屬性 指定屬性為基本型別,則直接返回該屬性值 如果指定屬性為實體物件,則返回格式{"code":"as1","name":"hk"} --> <param name="root">屬性名</param> <!--輸出多個Action屬性--> <param name="includeProperties">屬性名1,屬性名2...</param> <!--輸出所有屬性,不需要param標籤--> </result>
json需要導包,修改package繼承關係為json-default
八、UI標籤
1.表單 <s:form action="" method="" theme="simple" ></s:form>
2.文字框 <s:textfield name="userName" />
3.布林框 <s:checkbox name="marry" />
4.單選框 <s:radio name="sex" list="#{'M':'男','F':'女'}"/> 靜態初始化
<s:radio name="favoriteCities" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
5.多選框 <s:checkboxlist name="travelCities" list="#{'01':'北京','02':'上海','03':'廣州'}" /> 靜態初始化
<s:checkboxlist name="travelCities" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
6.下拉選 <s:select name="home" list="#{'01':'北京','02':'上海','03':'廣州'}" /> 靜態初始化
<s:select name="home" list="cities" listKey="cityCode" listValue="cityName" /> 動態初始化
九、攔截器
1.用途:攔截器適合封裝一些通用處理,便於重複利用。例如請求引數傳遞給Action屬性,日誌的記錄,許可權檢查,事務處理等。攔截器是通過配置方式呼叫,因此使用方法比較靈活,便於維護和擴充套件。
2.使用步驟
建立攔截器元件(建立一個類,實現Interceptor介面,並實現intercept方法;也可以繼承MethodFilterInterceptor,這種方式可以使action中某個方法不進行攔截)
public String intercept(ActionInvocation invocation){ //攔截器--前部分處理 invocation.invoke(); //攔截器--後續處理 }
註冊攔截器
<package> <interceptors> <interceptor name="別名" class="實現類"/> <!--其他攔截器--> </interceptors> </package>
引用攔截器(哪個Action希望被攔截器擴充套件,需要在此action配置下,引用攔截器)
<action>
<!--手動的使用一次系統預設的攔截器-->
<interceptor-ref name="defaultStack"/> <interceptor-ref name="攔截器別名"/> <!--可以寫多個-->
<!--可以使用excludeMethods引數屬性,設定不過濾的方法--> </action>
3.攔截器棧
<interceptor-stack name="myStack"> <interceptor-ref name="攔截器別名1"/> <interceptor-ref name="攔截器別名2"/> </interceptor-stack>
4.FileUpload攔截器
a)原理:首先FileUpload攔截器將表單中提交的檔案,以臨時檔案的形式儲存到伺服器臨時路徑下。之後FileUpload攔截器將該臨時檔案物件注入給Action,Action自主處理該臨時檔案。最後FileUpload攔截器刪除臨時檔案。
b)使用步驟
導包 commons-io.jar
Action:定義File型別屬性(如some),接受攔截器注入的臨時檔案物件。若想要獲取原始檔名,要定義String型別屬性,屬性名為File型別屬性+FileName(如someFileName)
表單設定:method="post", enctype="multipart/form-data"
c)設定限制(Struts2檔案上傳預設最大值為2097152B,即2M)
在struts.xml中重置預設限制值 <constant name="struts.multipart.maxSize" value="5000000" />