1. Struts2的核心配置(詳解) 本章內容目錄: 配置struts.xml文件 struts.xml文件 常量配置 包配置 包含配置 Action配置 實現Action控制類 配置Action 使用通配符 Action訪問Servlet API 通過ActionContext類訪問 通過特定接 ...
1. Struts2的核心配置(詳解)
本章內容目錄:
- 配置struts.xml文件
- struts.xml文件
- 常量配置
- 包配置
- 包含配置
- Action配置
- 實現Action控制類
- 配置Action
- 使用通配符
- Action訪問Servlet API
- 通過ActionContext類訪問
- 通過特定介面訪問、
- 通過ServletActionContext訪問
- Result結果類型
- 配置Result
- 預定義的結果類型
- dispatcher結果類型
- redirect結果類型
2. 具體內容
2.1 配置Struts.xml文件
2.1.1 Struts.xml文件
Struts2框架的核心配置文件是Struts.xml,該文件主要用來配置Action和請求的對應關係。Struts.xml文件可以被Struts2框架自動載入。
搭建好了的Struts2項目(可參考上一講如何搭建Struts2項目),其配置文件Struts.xml如下所示:
待配置的分塊如下(註意註釋部分):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!--constant元素用於常量的配置--> <constant name="struts.enable.DynamicMethodInvocation" value="false"/> <constant name="struts.devMode" value="ture"/> <!--package元素用於包配置--> <package name="default"namespace="/"extends="struts-default"> <!--配置Action--> <action name="index"> <!--配置Result--> <result type="dispatcher"> <param name="location">/index.jsp</param> </result> </action> </package>
<!--include元素用於包含配置--> <include file="example.xml"/> </struts>
簡單的包含關係:
2.1.2 常量配置
Struts2中常量配置共有3種方式:
- 在struts.xml文件中通過<constant>元素配置常量;
- 在struts.properties文件中配置常量;
- 在web.xml文件中通過<init-param>元素配置常量;
(1) 在Struts.xml文件中通過<constant>元素配置常量
在Struts.xml文件中通過<constant.../>來配置常量時,需要兩個必填的屬性name和value。
- name:該屬性指定了常量的常量名;
- value:該屬性指定了常量的常量值;
在Struts.xml文件中配置的示例代碼如下:
<struts> <!--設置預設編碼集為UTF-8--> <constant name="struts.enable.SlashesInActionNames" value="UTF-8"/> <!--設置使用開發模式--> <constant name="struts.devMode" value="ture"/> </struts>
要註意的是,在struts.properties文件能配置的常量都可以在struts.xml文件中用<constant...>元素來配置。
(2)在struts.properties文件是一個標準的properties文件,其格式為Key-Value對,即每個key對應一個value,key表示的是Struts2框架中的常量,而value表示的是常量值,具體配置如下:
###設置預設編碼集為UTF-8 struts.il8n.encoding=UTF-8 ###設置action請求的擴展名為action或者沒有擴展名 struts.action.extension=action, ###設置不使用開發模式 struts.devMode=false ###設置不開啟動態方法調用 struts.enable.DynamicMethodInvocation=false
上述代碼段中,=號的左邊的是key,右邊是key對應的value,另外,代碼片段中的###表示的是properties文件中的解釋信息(註釋),用於解釋說明。
(3)在web.xml文件中通過初始化參數配置常量
在web.xml文件中配置核心過濾器StrutsPrepareAndExecuteFilter時,通過初始化參數來配置常量。通過<filter>元素的<init-param>子元素指定,每個<init-param>元素配置了一個struts常量。在web.xml文件中通過初始化參數配置常量方式,如下列代碼段所示:
<filter> <!--指定struts2的核心過濾器--> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> <!--通過init-param元素配置struts2常量,配置預設編碼集為UTF-8--> <init-param> <param-name>struts.il8n.encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
需要註意的是, <init-param>標簽要放到<filter>之中。
此外,Struts2框架的載入常量有一定的順序,通常搜索順序如下:
- default.properties:該文件在struts2-core-2.3.24.jar文件中的org.apache.struts2包裡面;
- struts-default.xml:該文件保存在struts2-core-2.3.24.jar文件中;
- struts-plugin.xml:該文件保存在struts-Xxx-2.3.24.jar等Struts2插件JAR包中;
- struts.xml:該文件是Web應用自己的Struts配置文件Struts2配置文件;
- struts.properties:該文件是Web應用預設的Struts配置文件;
- web.xml:該文件是Web應用的配置文件;
2.1.3 包配置
Struts2框架的核心組件是Action和攔截器,它使用包來管理Action和攔截器。每個包就是多個Action、多個攔截器、多個攔截器引用的集合。在Struts.xml文件中,package元素定義了一個包配置,每個package元素定義了一個包配置。package常用屬性如下表所示:
屬性 | 說明 |
name | 必填屬性,指定包的名字,此名字是該包被其他包引用的key |
namespace | 可選屬性,該屬性定義該包的命名空間 |
extends |
可選屬性,指定該包繼承自其他包,可以繼承其他包的Action定義、 攔截器定義等。屬性直常設為“strruts-default” |
abstract |
可選屬性,他指定該包是否是一個抽象包,抽象包不能包含Action 定義。(例如:abstract=“true”---->抽象包) |
2.1.3 包含配置
Struts2預設只載入struts.xml文件,但一旦通過多個XML文件來配置Action,就必須通過struts.xml文件來包含其他配置文件。結下來示例一段代碼來說明;
<struts> <!--包含4個配置文件--> <!-- 不指定路徑,預設在src下時的方式 --> <include file="struts-shop.xml"/> <include file="struts-user.xml"/> <include file="struts-shoppingcart.xml"/> <!-- 配置文件在具體包中的方式 --> <include file="cn/intcast/action/struts-product.xml"/> </struts>
2.2 Action的配置
2.2.1 實現Action控制類
Action作為Struts框架的核心類,實現對用戶請求的處理,Action類被稱為業務邏輯控制器。一個Action類代表一次請求或調用,每個請求的動作都對應於一個相應的Action類,一個Action類是一個獨立的工作單元。也就是說,用戶的每次請求動作都對應於一個相應的Action類裡面,由這個Action類來進行處理。簡而言之,Action就是用來處理一次用戶請求的對象。
實現Action控制有3中方式:
(1) POJO的實現
Action可以不繼承特殊的類或不實現任何特殊介面,僅僅是一個POJO。POJO全稱是Plain Ordinary Java Object(簡單的Java對象),只要具有一部分getter/setter方法的類就可以稱作為POJO。一般這個POJO類中,要有一個公共的無參構造方法和一個execute()方法。execute方法是Action類的預設請求處理方法,其方法格式如下:
public String execute() throws Exeception { return "success"; }
execute()方法要求如下:
- 方法的許可權修飾符為public
- 返回一個字元串,就是指示的下一個頁面的Result
- 方法沒有參數
也就是說滿足上述要求的POJO都可以算作是Struts的Action實現,但在實際的開發中,通常會讓開發者自己編寫Action類實現Action介面或者繼承ActionSupport類。
(2)實現Action介面
(3)繼承ActionSupport類
(上述兩個小部分都是java的簡單實現,這篇文章不再贅述)
2.2.2 配置Action
Action映射是框架中的基本“工作單元”。Action映射就是將一個請求的URL映射到一個Action類,當一個Actio請求匹配某個Action名稱時,框架就使用這個映射來確定如何處理請求。在Struts.xml文件中,通過<action>元素對請求的Action和Action類進行配置。
<action>元素中共有4個屬性,具體說明如下:
屬性 | 說明 |
name | 必填屬性,標識Action,指定了Action所處理的請求的URL |
class | 可選屬性,指定Action對應的實現類 |
method | 可選屬性,指定請求Action時調用的方法 |
converter | 可選屬性,指定類型轉換器的類 |
需要註意的是,在配置action元素時,如果沒有指定class屬性直,則其預設直為com.opensymphony.work2.ActionSupport類,該預設類會使用預設的處理方法execute()方法來處理請求,實際上,ActionSupport類中的execute()不會做任何處理,而是直接返回success直。在配置<action>元素時,如果指定了method屬性,則該Action可以調用method屬性中指定的方法,如果不指定method屬性,則Action會調用execute()方法。
接下來看一個struts.xml文件中配置的action元素,代碼片段如下所示:(註意:action的配置在struts.xml的package包平配置的內部)
<action name="userAction"class="cn.itcast.action.UserAction"> <result>/success.jsp</result> </action>
<action>類的屬性直將在其他地方引用,例如.jsp頁面form表單的action屬性直;class屬性指明瞭Action的實現類。
2.2.3 使用通配符
在使用method屬性時,由於在Action類中有多個業務邏矩處理方法,在配置Action時,就需要使用多個action元素。在實現同樣功能的情況下減輕struts.xml配置文件的負擔,藉助於通配符映射。
使用通配符配置時,<package>元素的內容如下所示;
<package name="User"namespace="/user"extends="struts-default"> <action name="User_Action_*" class="cn.itcast.action.UserAction" method="(1)"> <result>/index.jsp</result> </action> </package>
註意對於result也可以採用通配符。
2.3 Action訪問Servlet API
在struts2中,Action並沒有直接和Servlet API進行耦合,也就是說,在Struts2的Action中不能直接訪問Servlet API。在實現業務邏輯時,經常要訪問Servlet中的對象,如session、request和application等。在struts2中,訪問Servlet API有三種方法。
2.3.1 通過ActionContest類訪問
ActionContext類訪問Servlet API的常用方法:
方法聲明 | 功能描述 |
void put(String key,Object value) | 將key-value鍵值對放入ActionContext中,模擬Servlet API中的HttpServletHttpServletRequest的setAttribute()方法 |
Object get(String key) | 通過參數key來查找當前ActionContext中的直 |
Map<String,Object> getApplication() |
返回一個Aplication級的Map對象 |
static ActionContext getContext() |
獲取當前線程的ActionContext對象 |
Map<String,Object> getParameters() | 返回一個包含所有HttpServletRequest參數信息的Map對象 |
Map<String,Object> getSession() | 返回一個Map類型的HttpSession |
void setApplication (Map<String,Object>application) | 設置Application上下文 |
void setSession (Map<String,Object>session) | 設置一個Map類型的Session |
2.3.2 通過特定介面訪問
- ServletRequestAware:實現該介面的Action可以直接訪問Web應用的HttpServletRequest實例;
- RequestResponseAware:實現該介面的Action可以直接訪問Web應用的HttpServletResponse實例;
- SessionAware:實現該介面的Action可以直接訪問Web應用的ServletContext實例;
2.3.3 通過ServletActionContext訪問
- static HttpServletRequest getRequest():獲取Web應用的HttpServletRequest對象;
- static HttpServletResponse getResponse():獲取Web應用的HttpServletResponse對象;
- static ServletContext getServletContext():獲取Web應用中的ServletContext對象;
- static PageContext getPageContext():獲取Web應用中的PageContext對象。
2.4 Result結果類型
2.4.1 配置Result
在struts.xml文件中進行Result的配置,使用<result>元素來配置Result邏輯視圖與無力視圖之間的映射,<result>元素可以有name和type屬性,但這兩種屬性都不是必選的;
- name屬性:指定邏輯視圖的名稱,預設值是success;
- type屬性:指定返回的視圖資源類型,不同的類型代表不同的結果輸出,預設值是dispatcher。
在Struts,xml文件中的<result>元素配置代碼如下:
<action name="logiAction"class="cn.itcast.action.loginAction"> <result name="success"type="dispatcher"> <param name="location">/success.jsp</param> </result> </action>
註意:<param>子元素的name屬性有兩個值,分別如下:
- location:指定該邏輯視圖所對應的實際視圖資源;
- parse:指定在邏輯視圖資源名稱中是否可以使用OGNL表達式。預設值為true,表示可以使用,如果設為false,則表示不支持。
上述配置可以簡化為:
<action name="logiAction" class="cn.itcast.action.loginAction"> <result>/success.jsp</result> </action>
需要註意的是,在Result中,指定實際資源位置時,可以使用絕對路徑,也可以使用相對路徑。絕對路徑以斜杠(/)開頭,例如<result>/success.jsp<result>,相當於當前Web應用程式的上下文路徑;相對路徑不以斜杠開頭,例如<result>success.jsp</result>,相當於當前執行的Action路徑。
2.4.2 預定義的結果類型
在struts2中,當框架調用Action對請求進行處理後,就要向用戶呈現一個結果視圖。在struts2中,預定義了多種ResultType,其實就是定義了多種展示結果技術。
每個<result-type>元素都是一種視圖技術或者跳轉方式的封裝,其中的name屬性指出在<result>元素中如何引用這種視圖技術或者跳轉方式,對應著<result>元素的type屬性。struts2中預定義的ResultTyoe如下所示;
屬性 | 說明 |
chain | 用來處理Action鏈,被跳轉的Action中仍能獲取送上個頁面的直、如request信息 |
dispatcher | 用來轉向頁面,通常處理JSP,預設的結果類型 |
freemarker | 用來整合FreeWorker模板結果類型 |
httpheader | 用來處理特殊的HTTP行為結果類型 |
redirect | 重定向到一個URL,被跳轉的頁面中丟失傳遞的信息 |
redirectAction | 重定向到一個Action,跳轉的頁面中丟失傳遞的信息 |
stream | 向瀏覽器發送InputStream對象,通常用來處理文件下載,還可用於Ajax數據 |
velocity | 用來整合Velocity木板結果類型 |
xslt | 用來整合XML/ XSLT結果類型 |
plainText | 顯示原始文件內容,例如文件源代碼 |
postback | 使得當前請求參數以表單形式提交 |
上表列舉了Struts2中預定義的全部11種結果類型,其中dispatcher是預設的結果類型,主要用來與JSP整合。在這全部11中結果類型中,dispatcher和redirect是比較常用的結果集。
需要註意的是,dispatcher結果類型是將請求轉發到JSP視圖資源,而redirect類型是將請求重定向到JSP視圖資源。他們之間最大的差別就是一個是請求轉發、一個是請求重定向。如果重定向了請求,那麼將丟失所有參數,其中包括Action的處理結果。
2.4.3 dispatcher結果類型
dispatcher結果類型用來表示“轉發”到指定的結果資源,他是struts2的預設結果類型。dispatcher結果類型實現的是org.apache. struts2. dispatcher.ServletDispatcherResult,該類有location和parse兩個屬性,可以通過struts.xml配置文件中的result元素的param資源書來設置,代碼如下:
<result name="success"type="dispatcher"> <param name="location">/success.jsp</param> <param name="parse">true</param> </result>
上述代碼中,location參數用於指定Action執行完畢後要轉向的目標;parse參數是一個布爾型的值,預設是true,表示解析location參數中的OGNL表達式子,如果是faulse,則不解析。
2.4.4 redirect結果類型
redirect結果類型用來重定向到指定的結果資源,該資源可以是JSP文件,也可以是Action類。使用redirect結果類型時,系統將調用HttpServletResponse的sendRedirect()方法將請求重定向到指定的URL。
redirect結果類型實現的類是org.apache.struts2.dispatcher.ServletRedirectResult。在使用redirect時,用戶要完成一次和伺服器之間的交互,瀏覽器需要發送兩次請求,請求過程如下圖所示:
使用redirect結果類型的工作過程如下:
- 瀏覽器發送一個請求,Struts框架調用對應的Action實例對請求進行處理;
- Action返回“success”結果字元串,Struts2框架根據這個結果選擇對應的結果類型,這裡使用的是redirect結果類型;
- ServletRedirectResult在內部使用HttpServletResponse的sendRedirect()方法將請求重新定向到目標資源;
- 瀏覽器重新發送一個針對目標資源的新請求;
- 目標資源作為響應呈現給用戶。
代碼:
<action name="logiAction" class="cn.itcast.action.loginAction"> <result name="success"type="redirect">/success.jsp</result> <result name="error"type="dispatcher">/error.jsp</result> </action>
上述配置中,<result>元素使用redirect類型,表示當Action處理請求後重新生成一個請求。
PS:什麼是請求轉發和請求重定向,具體區別是什麼?(參考,http://blog.csdn.net/meiyalei/article/details/2129120)
解釋一:
一句話,轉發是伺服器行為,重定向是客戶端行為。看兩個動作的工作流程:
轉發過程:客戶瀏覽器發送http請求----->web伺服器接受此請求----->調用內部的一個方法在容器內部完成請求處理和轉發動作----->將目標資源發送給客戶。在這裡,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器內的request。在客戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑,也就是說客戶是感覺不到伺服器做了轉發的。轉發行為是瀏覽器只做了一次訪問請求。
重定向過程:客戶瀏覽器發送http請求----->web伺服器接受後發送302狀態碼響應及對應新的location給客戶瀏覽器----->客戶瀏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location地址----->伺服器根據此請求尋找資源併發送給客戶。在這裡location可以重定向到任意URL,既然是瀏覽器重新發出了請求,則就沒有什麼request傳遞的概念了。在客戶瀏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到地址的變化的。重定向行為是瀏覽器做了至少兩次的訪問請求的。
解釋二:
請求重定向,其實是兩次request, 第一次,客戶端request,伺服器響應,並response回來,告訴瀏覽器,你應該去B。這個時候瀏覽器可以看到地址變了,而且瀏覽器的歷史回退按鈕也亮了。重定向可以訪問自己web應用以外的資源。在重定向的過程中,傳輸的信息會被丟失。
請求轉發,是伺服器內部把對一個request/response的處理權,移交給另外一個 對於客戶端而言,它只知道自己最早請求的那個A,而不知道中間的B,甚至C、D。 傳輸的信息不會丟失。
解釋三:
假設你去辦理某個執照,
請求重定向:你先去了A局,A局的人說:“這個事情不歸我們管,去B局”,然後,你就從A退了出來,自己乘車去了B局。
請求轉發:你先去了A局,A局看了以後,知道這個事情其實應該B局來管,但是他沒有把你退回來,而是讓你坐一會兒,自己到後面辦公室聯繫了B的人,讓他們辦好後,送了過來。