Struts 2 入門: 一:Struts 2執行流程: 1 客戶端發送請求; 2這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其他框架的集成很有幫助,例如:SiteMeshPlugin) 3接著 ...
Struts 2 入門:
一:Struts 2執行流程:
1 客戶端發送請求;
2這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其他框架的集成很有幫助,例如:SiteMeshPlugin)
3接著FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否需要調用某個Action。FilterDispatcher的功能如下:
(1)執行Actions
(2)清除ActionContext
(3)維護靜態內容
(4)清除request生命周期內的XWork的interceptors
4如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5 ActionProxy通過ConfigurationManager詢問框架的配置文件,找到需要調用的Action類
6ActionProxy創建一個ActionInvocation的實例。
7ActionInvocation實例使用命名模式來調用,在調用Action的過程前後,涉及到相關攔截器(Intercepter)的調用。
8一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。在表示的過程中可以使用Struts2框架中繼承的標簽。在這個過程中需要涉及到ActionMapper
二:攔截器與過濾器:
1、攔截器是基於java反射機制的,而過濾器是基於函數回調的。2、過濾器依賴於servlet容器,而攔截器不依賴於servlet容器。
3、攔截器只能對Action請求起作用,而過濾器則可以對幾乎所有請求起作用。
4、攔截器可以訪問Action上下文、值棧里的對象,而過濾器不能。
5、在Action的生命周期中,攔截器可以多次調用,而過濾器只能在容器初始化時被調用一次。
在上述過程中所有的對象(Action,Results,Interceptors,等)都是通過ObjectFactory來創建的。Struts2的目標很簡單--使Web開發變得更加容易。為了達成這一目標,Struts2中提供了很多新特性,比如智能的預設設置、annotation的使用以及"慣例重於配置"原則的應用,而這一切都大大減少了XML配置。Struts2中的Action都是POJO,這一方面增強了Action本身的可測試性,另一方面也減小了框架內部的耦合度,而HTML表單中的輸入項都被轉換成了恰當的類型以供action使用。開發人員還可以通過攔截器(可以自定義攔截器或者使用Struts2提供的攔截器)來對請求進行預處理和後處理,這樣一來,處理請求就變得更加模塊化,從而進一步減小耦合度。模塊化是一個通用的主題--可以通過插件機制來對框架進行擴展;開發人員可以使用自定義的實現來替換掉框架的關鍵類,從而獲得框架本身所不具備的功能;可以用標簽來渲染多種主題(包括自定義的主題);Action執行完畢以後,可以有多種結果類型--包括渲染JSP頁面,Velocity和Freemarker模板,但並不僅限於這些
三:Struts 2概述
- Struts 2缺陷:
(1.)表單成支持單一
(2.)對Servlet api的依賴
(3.)不利於代碼的重用
2.Struts 2的獲取:
資源包:http://strust.apache.org/download.cgi
- Strust 2項目的基礎jar文件:
文件名 --------------------- 說明
Struts2-core-xxx.jar :Struts2框架的核心類庫。
xwork-core-xxx.jar:XWork類庫,Struts2的構建基礎。
Ognl-xxx.jar:Struts2使用的一種表達式語音類庫
Freemarker-xxx.jar:Struts2的標簽模板使用類庫
Javassist-xxx.GA.jar:對位元組代碼進行處理
Commons-fileupload-xxx.jar:文件上傳時需要使用
Commons-io-xxx.jar:Java Io擴展
Commons-lang-xxx.jar:包含一些資料庫類型的工具類。
四:Action介面中常量字元串的邏輯含義
常量---------值------------------------------邏輯含義
SUCCESS: success:表示程式處理異常,並返回給用戶成功後的結果
NONE none 表示處理正常結束,但不返回給用戶任何提示
ERROR error 表示處理結果失敗
INPUT input 表示需要更多用戶輸入才能順利執行
LOGIN login 表示需要用戶正確登錄後才能順利執行
五:Struts 2配置詳解
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
<!-- include節點是struts2中組件化的方式 可以將每個功能模塊獨立到一個xml配置文件中 然後用include節點引用 -->
<include file="struts-default.xml"></include>
<!-- package提供了將多個Action組織為一個模塊的方式
package的名字必須是唯一的 package可以擴展 當一個package擴展自
另一個package時該package會在本身配置的基礎上加入擴展的package
的配置 父package必須在子package前配置
name:package名稱
extends:繼承的父package名稱
abstract:設置package的屬性為抽象的 抽象的package不能定義action 值true:false
namespace:定義package命名空間 該命名空間影響到url的地址,例如此命名空間為/test那麼訪問是的地址為http://localhost:8080/struts2/test/XX.action
-->
<package name="com.kay.struts2" extends="struts-default" namespace="/test">
<interceptors>
<!-- 定義攔截器
name:攔截器名稱
class:攔截器類路徑
-->
<interceptor name="timer" class="com.kay.timer"></interceptor>
<interceptor name="logger" class="com.kay.logger"></interceptor>
<!-- 定義攔截器棧 -->
<interceptor-stack name="mystack">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定義預設的攔截器 每個Action都會自動引用
如果Action中引用了其它的攔截器 預設的攔截器將無效 -->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!-- 全局results配置 -->
<global-results>
<result name="input">/error.jsp</result>
</global-results>
<!-- Action配置 一個Action可以被多次映射(只要action配置中的name不同)
name:action名稱
class: 對應的類的路徑
method: 調用Action中的方法名
-->
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!-- 引用攔截器
name:攔截器名稱或攔截器棧名稱
-->
<interceptor-ref name="timer"></interceptor-ref>
<!-- 節點配置
name : result名稱 和Action中返回的值相同
type : result類型 不寫則選用superpackage的type struts-default.xml中的預設為dispatcher
-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!-- 參數設置
name:對應Action中的get/set方法
-->
<param name="url">http://www.sina.com</param>
</action>
</package>
</struts>
補充:
struts.xml是我們在開發中利用率最高的文件,也是Struts2中最重要的配置文件。
一下分別介紹一下幾個struts.xml中常用到的標簽
1、<include>
利用include標簽,可以將一個struts.xml配置文件分割成多個配置文件,然後在struts.xml中使用<include>標簽引入其他配置文件。
比如一個網上購物程式,可以把用戶配置、商品配置、訂單配置分別放在3個配置文件user.xml、goods.xml和order.xml中,然後在struts.xml中將這3個配置文件引入:
struts.xml:
1 2 3 4 5 6 7 8 9 10 |
|
user.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
2、<constant>
在之前提到struts.properties配置文件的介紹中,我們曾經提到所有在struts.properties文件中定義的屬性,都可以配置在struts.xml文件中。而在struts.xml中,是通過<constant>標簽來進行配置的:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
3、<package>
1、包屬性介紹
在Struts2框架中是通過包來管理action、result、interceptor、interceptor-stack等配置信息的。包屬性如下:
屬性 |
是否必需 |
描述 |
name |
是 |
包名,作為其它包應用本包的標記 |
extends |
否 |
設置本包繼承其它包 |
namespace |
否 |
設置包的命名空間 |
abstact |
否 |
設置為抽象包 |
2、extends屬性的詳解
當一個包通過配置extends屬性繼承了另一個包的時候,該包將會繼承父包中所有的配置,包括action、result、interceptor等。
由於包信息的獲取是按照配置文件的先後順序進行的,所以父包必須在子包之前被定義。
通常我們配置struts.xml的時候,都繼承一個名為“struts-default.xml”的包,這是struts2中內置的包。
3、namespace的詳解
namespace主要是針對大型項目中Action的管理,更重要的是解決Action重名問題,因為不在同一個命名空間的Action可以使用相同的Action名的。
1)如果使用命名空間則URL將改變
比如我們有一下配置文件
1 2 3 4 5 |
|
則此配置下的Action的URL為http://localhost:8080/login.action
假如為這個包指定了命名空間
1 2 3 4 5 |
|
則此配置下的Action的URL為http://localhost:8080/user/login.action
2)預設命名空間
Struts2中如果沒有為某個包指定命名空間,該包使用預設的命名空間,預設的命名空間總是""。
3)指定根命名空間
當設置了命名空間為“/”,即指定了包的命名空間為根命名空間時,此時所有根路徑下的Action請求都會去這個包中查找對應的資源信息。
假若前例中路徑為http://localhost:8080/login.action則所有http://localhost:8080/*.action都會到設置為根命名空間的包中尋找資源。
4、<action>與<result>
1、<action>屬性介紹
屬性名稱 |
是否必須 |
功能描述 |
name |
是 |
請求的Action名稱 |
class |
否 |
Action處理類對應具體路徑 |
method |
否 |
指定Action中的方法名 |
converter |
否 |
指定Action使用的類型轉換器 |
如果沒有指定method則預設執行Action中的execute方法。
2、<result>屬性介紹
屬性名稱 |
是否必須 |
功能描述 |
name |
否 |
對應Action返回邏輯視圖名稱,預設為success |
type |
否 |
返回結果類型,預設為dispatcher |
3、通配符的使用
隨著result的增加,struts.xml文件也會隨之變得越來越複雜。那麼就可以使用通配符來簡化配置:
例如下麵這個案例:
Action為Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
struts.xml中配置為
1 2 3 4 5 |
|
4、訪問Action方法的另一種實現方式
在Struts2中如果要訪問Action中的指定方法,還可以通過改變URL請求來實現,將原本的“Action名稱.action”改為“Action名稱!方法名稱.action”在struts.xml中就不需要指定方法名了。
5、<exception-mapping>與<global-exception-mapping>
這兩個標簽都是用來配置發生異常時對應的視圖信息的,只不過一個是Action範圍的,一個是包範圍的,當同一類型異常在兩個範圍都被配置時,Action範圍的優先順序要高於包範圍的優先順序.這兩個標簽包含的屬性也是一樣的:
屬性名稱 |
是否必須 |
功能描述 |
name |
否 |
用來表示該異常配置信息 |
result |
是 |
指定發生異常時顯示的視圖信息,這裡要配置為邏輯視圖 |
exception |
是 |
指定異常類型 |
兩個標簽的示例代碼為:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
6、<default-class-ref>
當我們在配置Action的時候,如果沒有為某個Action指定具體的class值時,系統將自動引用<default-class-ref>標簽中所指定的類。在Struts2框架中,系統預設的class為ActionSupport,該配置我們可以在xwork的核心包下的xwork-default.xml文件中找到。
有特殊需要時,可以手動指定預設的class
1 2 3 4 5 6 7 |
|
在struts.xml中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
7、<default-action-ref>
如果在請求一個沒有定義過的Action資源時,系統就會拋出404錯誤。這種錯誤不可避免,但這樣的頁面並不友好。我們可以使用<default-action-ref>來指定一個預設的Action,如果系統沒有找到指定的Action,就會指定來調用這個預設的Action。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
8、<default-interceptor-ref>
該標簽用來設置整個包範圍內所有Action所要應用的預設攔截器信息。事實上我們的包繼承了struts-default包以後,使用的是Struts的預設設置。我們可以在struts-default.xml中找到相關配置:
1 |
|
在實際開發過程中,如果我們有特殊的需求是可以改變預設攔截器配置的。當時一旦更改這個配置,“defaultStack”將不再被引用,需要手動最加。
9、<interceptors>
通過該標簽可以向Struts2框架中註冊攔截器或者攔截器棧,一般多用於自定義攔截器或攔截器棧的註冊。該標簽使用方法如下:
1 2 3 4 5 6 |
|
10、<interceptor-ref>
通過該標簽可以為其所在的Action添加攔截器功能。當為某個Action單獨添加攔截器功能後,<default-interceptor-ref>中所指定的攔截器將不再對這個Action起作用。
11、<global-results>
該標簽用於設置包範圍內的全局結果集。在多個Action返回相同邏輯視圖的情況下,可以通過<global-results>標簽統一配置這些物理視圖所對應的邏輯視圖。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
六:Struts 2訪問Servlet API對象
- 最常用的Servlet api三個介面:
HttpServletRequest
HttpSession
ServletContext
- Servlet API解耦的訪問方式:
//解偶方式獲得session request
ActionContext context=ActionContext.getContext();
//獲得session
Map session=context.getSession();
//獲得request
Map request=(Map)context.get("request");
- 關於註入的概念:
簡單的說就是通過框架自動對Action屬性進行賦值,和Spring中的依賴註入類似。
七:Struts 2標簽:
1.<%@ taglib prefix=”s” uri=”/struts-tags”%>
2.UI標簽:可分為三大部分:
表單標簽
非表單標簽
Ajax標簽
表單標簽的圖解:
標簽 |
說明 |
<s:form>…..</s:form> |
獲取相應的form值 |
<s:textfield>……..</> |
文本框輸入 |
<s:password>……..</> |
密碼框輸入 |
<s:textarea>………</> |
文本域輸入 |
<s:radio>……………..</> |
單選按鈕 |
<s:checkbox>………….</> |
覆選框 |
<s:submit>………….</> |
提交按鈕 |
<s:reset>………………</> |
重置按鈕 |
<s:hidden>……………</> |
隱藏域標簽 |
|
|
- 通用標簽:
名稱 |
標簽 |
根據表達式的值,判斷將要執行的內容
|
條件標簽 |
<s:if>…..</> <s:elseif>……</> <s:else>……….</>
|
|
迭代標簽 |
<s:iterator>………….</> |
用於遍歷集合 |
|
|
|
註意:
(1.)三個標簽中只有<s:if……./>標簽可以單獨使用。
(2.)三個標簽可以組合使用<s:elseif……../>標簽與<s:else……/>標簽不能單獨使用,必須與<s:if…../>標簽結合才能使用。
(3.)<s:if……./>標簽可以與多個<s:elseif……./>結合使用,但是只能與一個<s:else……../>標簽結合在一起。