一、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> <!-- 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" />