簡單的說,Result是Action執行完后返回的一個字符串,它指示了Action執行完成后,下一個頁面在哪里。Result僅僅是個字符串,僅僅是用來指示下一個頁面的,那么如何才能夠到達下一個頁面呢?下一個頁面如何能正確地展示結果呢?這就該引出一個新概念——ResultType,所謂ResultType,指的是具體執行Result的類,由它來決定采用哪一種視圖技術,將執行結果展現給用戶。
很多時候,我們并不去區分Result和ResultType,而是籠統的稱為Result。因此,Result除了當作上面講述的字符串來理解外,還可以把Result當作技術,把Result當作實現MVC模型中的View視圖的技術,也就是ResultType來看待。
在Struts2中,可以使用多種視圖技術,如jsp、freemarker、velocity、jfreechart等等,同時,Struts2也支持用戶自定義ResultType,來打造自己的視圖技術。
1)預定義ResultType
在Struts2中,預定義了很多ResultType,其實就是定義了很多展示結果的技術。Struts2把內置的<result-type>都放在struts-default包中。struts-default包就是我們配置的包的父包,這個包定義在struts-2.3.16.3.jar包中的根目錄下的文件struts-default.xml中。在這個包中,可以找到相關的<result-type>的定義,<result-types>元素是<package>元素的直接子元素。Struts2預定義如下:
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" /> </result-types>
上面的每一個<result-type>元素都是一種視圖技術或跳轉方式的封裝。其中的name屬性是在<result>元素中如何引用這種視圖技術或跳轉方式,對應著<result>元素的type屬性的值。
可能有朋友會說,我們在配置<result>元素的時候,沒有配置過type屬性嘛。沒錯,你確實沒有配置過,原因就在于Struts2里面設置了默認的type,如果你沒有配置,默認就是“dispatcher”。這個“dispatcher”的技術就相當于在Servlet里面的“RequestDispatcher”的技術,也就是一個頁面跳轉的技術。而class屬性是這種視圖技術或跳轉方式的具體實現類,這些實現類都已經是Struts2實現好的,我們只需要引用就可以了。
2)Result的配置
- 配置name屬性
name屬性是用來跟Action的execute方法返回的字符串相對應的,用來指示Action運行后跳轉到的下一個頁面,因此name屬性的值可以是任意字符串。比如有如下的execute方法:
public String execute() throws Exception { return "toWelcome"; }
那么,這里返回的“toWelcome”,在struts.xml里面就有如下的配置來對應:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <result name="toWelcome">/s2impl/welcome.jsp</result> </action>
如果不設置的話,默認值為“success”,正好和Action中的“SUCCESS”這個常量相對應,那樣的話,execute方法就應該返回SUCCESS,如下:
public String execute() throws Exception { return this.SUCCESS; }
此時在struts.xml里面就有如下的配置來對應:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <result>/s2impl/welcome.jsp</result> <!-- 或者如下的配置 <result name="success">/s2impl/welcome.jsp</result> --> </action>
- 配置type屬性
<result>元素的type屬性也可以是任意字符串,不過,一定是某一個<result-type>元素的name屬性。在沒有自定義ResultType的情況下,type屬性的值,就是在struts-default.xml中所定義的<result-type>的name屬性的值。比如:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <result name="toWelcome" type="dispatcher">/s2impl/welcome.jsp</result> </action>
這里的“dispatcher”就是在struts-default.xml中所定義的默認的<result-type>的name屬性值。既然是默認的,那就可以不用配置,也就是說,上面的配置跟如下配置是等價的,示例如下:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <result name="toWelcome">/s2impl/welcome.jsp</result> </action>
3)全局Result
- 配置方法
全局Result本身沒有任何的特異之處,同樣是配置name屬性和type屬性,包括如何指定jsp的位置都和普通的Result一樣,只不過其<result>元素并不是<action>元素的子元素,而是作為<global-results>元素的子元素,而<global-results>元素又是<package>元素的子元素,示例如下:
<package name="helloworld" extends="struts-default"> <global-results> <result name="toLogin">/login.jsp</result> </global-results> <action ……> …… </action> </package>
- 搜尋Result的順序
在有了全局Result之后,需要討論一下在Action運行之后,根據execute方法的返回值尋找Result順序了。
(1)首先,先找自己的<action>元素內的<result>元素是否有匹配的,如果有就執行這個Result,如果沒有,下一步。
(2)其次,再找自己的<action>所在的包的全局Result,看看是否有匹配的,如果有就執行這個Result,如果沒有,下一步。
(3)再次,遞歸的尋找自己的包的父包、祖父包中的全局Result是否有匹配的,如果有就執行這個Result,如果沒有,下一步。
(4)最后,如果上述三種情況都沒有匹配的Result的話,則拋出Exception。
注意:如果出現同名的Result,上述的順序也是Result之間的優先順序。也就是說,如果Action的execute方法返回的字符串,在局部Result和全局Result中都有能匹配的配置,那么以局部Result為準。
文章列表