前言
Struts 2中的Result是作为返回结果的,时当一个action处理完之后返回字符串的结果码。框架可以根据这个返回的字符串,映射到指定的页面。result元素可以分为两部分:一是结果映射,一部分是返回结果类型。
结果映射
result有两个属性可以配置:name属性和type属性。其中的name属性主要用来指定资源的逻辑名称,实际名称在标签内部指定。type属性就是result的返回类型。要注意的是,这两个属性都不是必须的,当我们没有配置这两个属性的时候,实际上框架为我们指定了默认值,其中name属性的默认值是success,type属性的默认值是dispatcher(转发)。正因为框架为我们设定了默认值才可以不用配置。
我们之前的配置都是使用result直接配置,实际上result标签还有一个子标签param
,该标签可以为result指定实际资源的位置,其有有一个必需的属性name,实际上就是之前文章中result的配置的资源。比如下面的配置:
<action name="login" class="action.LoginAction">
<result>
<!-- param的location用于指示资源的位置,标签的内容是参数的值 -->
<param name="location">/success.jsp</param>
</result>
<result name="error">/error.jsp</result>
</action>
这里指示资源的实际位置使用param标签,但是如果result的type属性是dispatcher的时候,上面的param标签是可以直接省略的,这也是前面没有写param标签也没有报错的原因。
结果类型
结果类型中常用的有四种:dispatcher、redirect、redirectAction和chain。其中dispatcher已经说过相当转发,redirect相当于重定向,redirecAction也是重定向,只不过使用该结果类型的时候,一般是重定向到某个action,最后一种主要用于action的链式处理。其他的还有plainText(用于显示页面的原始内容,比如Servlet或者jsp的源代码)、xslt等。
第1种:dispatcher
dispatcher也是框架默认的结果类型,其实现类是org.apache.struts2.dispatcher.ServletDispatcherResult,该类中有两个属性:location和parse。它们也可以在struts.xml文件中直接配置:
<result type="dispatcher">
<!-- param的location用于指示资源的位置,标签的内容是参数的值 -->
<param name="location">/success.jsp</param>
<param name="parse">true</param>
</result>
其中的location参数用于指定资源的实际位置,该参数也是框架默认添加的;parse参数是一个布尔变量,当为true的时候,表示将解析location参数中的OGNL表达式(后面还会介绍)。框架中parse参数的默认值也是true。
第2种:redirect
当使用该结果类型的时候,框架后台会使用response对象的sendRedirect方法进行重定向,重定向与转发还是不同的,具体体现在以下几个方面:
- 重定向会发生两次请求,转发只会发生一次请求
- 重定向的时候,浏览器的地址栏会发生变化,而转发地址栏是无变化的
- 重定向的实质是服务器告诉浏览器去另外的地方寻找资源,所以地址栏会发生变化,而转发是在服务器内部发生的,所以地址栏不会发生变化
- 由于重定向是两次请求,所以第二次请求会话保存的信息是无效的,而转发的时候,会话仍然有效,因为仍然是原来的请求。
如果需要在重定向的时候把原来的有关信息发送到重定向后的页面中,则需要使用OGNL表达式${username}(比如在登录成功后重定向到欢迎页面,在欢迎页面就可以使用OGNL表达式把用户名传递过去),比如下面的配置:
<!-- 登录Action -->
<action name="login" class="action.LoginAction">
<result type="redirect">/success.jsp?user.username=${user.username}</result>
<result name="error">/error.jsp</result>
</action>
在登录成功之后重定向到success.jsp页面的时候,可以观察到浏览器的地址栏把用户名作为参数传递到success.jsp页面。
第3种:redirectAction
此种结果类型与redirect一样,底层都是调用Response对象的sendRedirect方法进行重定向的,这两者的区别是redirect结果类型一般是针对视图的,而redirectAction则是重定向到某个action,所以如果在action处理之后还要交给另一个action继续处理,那么使用redirecAction结果类型。
redirecAction结果类型有两个参数:actionName(指定需要重定向的action)和namespace(指定action所在的命名空间,如果没有指定该参数,框架会从默认的namespace中去寻找)。比如下面的配置:
<!-- HelloWorld演示程序 -->
<action name="hello" class="example.HelloWorld">
<!-- 重定向到/user命名空间下的UserAction -->
<result type="redirectAction">
<!-- 指定需要重定向的action的name属性 -->
<param name="actionName">userAction</param>
<!-- 指定重定向的action所在的namespace -->
<param name="namespace">/user</param>
</result>
</action>
<!-- 登录Action -->
<action name="login" class="action.LoginAction">
<result type="redirect">/success.jsp?user.username=${user.username}</result>
<!-- 重定向到同一namespace下的name属性为error的action -->
<result type="redirectAction">
<!-- 同一namespace下的action不需要指定namespace参数 -->
<param name="actionName">error</param>
</result>
</action>
<action name="error">
<result>/error.jsp</result>
</action>
全局结果
全局结果的的主要作用是,在有多个action都需要返回到某个页面的时候,就可以全局结果。比如在电商网站购物的时候,查看订单,添加商品到购物车都需要先登录,那么就可以把登录作为一个全局结果。全局结果是在包中定义的,这样该包下的所有action都可以共享该全局结果了。
配置全局结果的方式与在action中直接配置result不太一样,全局结果是在global-results标签中定义的。比如下面的配置:
<!-- 全局结果配置 -->
<global-results>
<result name="error">/error.jsp</result>
<result name="login" type="redirectAction">login!login</result>
</global-results>