struts2 之三:result返回结果

前言

Structs2中的result是作为返回结果的,当一个action处理完之后返回字符串的结果码。框架可以根据这个返回的字符串,映射到指定的页面。Result元素可以分为两部分:一是结果映射,一部分是返回结果类型

结果映射
Result有两个属性可以配置:name属性和type属性,其中name属性主要用来指定资源的逻辑名称,实际名称在标签内指定。Type属性就是result返回的类型,这两个属性不是必须的。其中默认情况下,name为success,type为dispatch(转发)
另外,result标签还有一个子标签param,该标签可以为result指定实际资源位置,其中属性name为必填,而当type为dispatch时,param可以省略不写

针对上面,不妨先模拟一个案例

1
2
3
4
5
<action name="helloworld" class="com.zwl.action.helloworld">
<result type="dispatcher">
<param name="location">/success.jsp</param>
</result>
</action>

这里的location是用于指示资源的位置,标签内的内容是参数的值

对应我们习惯写的形式为

1
2
3
4
5
<action name="helloworld" class="com.zwl.action.helloworld">
<result name="success">
/success.jsp
</result>
</action>

结果类型:
常用的有四种,dispatch、redirect、redirectAction和chain,其中dispatch相当于转发,redirect相当于重定向,redirectAction也是重定向,但是它是重定向到某个action,而chain则是利用action的链式处理

第一种:dispatch
它是系统默认的结果类型,其有两个属性,localtion和parse,配置如下

1
2
3
4
<result type="dispatcher">
<param name="location">/success.jsp</param>
<param name="parse">true</param>
</result>

其中parse是一个布尔类型,当为true时,表示解析localtion参数中的OGNL表达式,默认是true

第二种:redirect
当使用该类型时,框架后台会使用response对象的sendRedirect方法进行重定向,下面先简单对比一下重定向与转发的区别:
一:重定向会发生两次请求,转发只会发生一次请求
重定向的时候,浏览器的地址栏会发生变化,而转发的地址栏是无变化的
重定向的实质是服务器告诉浏览器去另外的地方寻找资源,所以地址栏会发生变化,而转发则是在服务器内部发生的,所以地址栏不会发生变化
由于重定向是两次请求,所以第二次请求的会话保存的信息是无效的,而转发的时候会话仍然有效,因为请求不变
对于重定向中会话仍然有效的方法是在配置文件中使用OGNL表达式,将参数传递过去
对于以上内容,不妨一个实例来的具体点

首先是上面的dispatch
如之前的hello world入门程序,最终观察地址栏和参数是可以接收到的

当type为redirect时

1
2
3
4
5
<action name="helloworld" class="com.zwl.action.helloworld">
<result type="redirect">
/success.jsp
</result>
</action>

观察地址栏是显示jsp的,但是参数是无法接收到的
那么如何解决了?

1
2
3
4
5
<action name="helloworld" class="com.zwl.action.helloworld">
<result name="success" type="redirect">
/success.jsp?user=${use.msg}
</result>
</action>

即带一个参数,注意此时的话,在success.jsp中值就不在值栈中了,因为不经过action,所以应该用如下方法取出

1
2
3
<body>
<s:property value="#parameters.user"/>
</body>

第三种:redirectAction,
其底层都是通过Response对象的sendRedirect方法进行重定向的,只不过它是重定向到某个action,所以如果一个action处理完之后还要交给另一个action据需处理,则使用该类型。
它的结果类型有两个参数,actionName(指定需要重定向的action)和namespace(指定action所在的命名空间,如果没有指定该参数,框架会从默认的namespace中去寻找)

1
2
3
4
5
6
7
<package name="default" namespace="/" extends="struts-default">
<action name="helloworld" class="com.zwl.action.helloworld">
<result type="redirectAction">
<param name="actionName">helloworld1</param>
<param name="namespace">/</param>
</result>
</action>

第四种:chain
一样,也是跳转到某个action

1
2
3
<action name="r3">
<result type="chain">r1</result>
</action>

接下来,进行简单对比
Redirect和redirectAciton都是客户端跳转,
而dispatch和chain都是服务器端跳转

全局action:
当有多个action都需要返回某个页面的时候,就可以用到全局结果
即在同一个包下所有的action都共享该result,如下所示

1
2
3
4
5
6
<global-results>
<result name="success">/success.jsp</result>
</global-results>
<action name="helloworld" class="com.zwl.action.helloworld">
</action>

仍然操作之前的步骤,结果仍能执行全局中的result

Namespace
Namespace决定了action的访问路径,默认为“”,可以接收所有路径的action,如果没有找到相应的namespace时,则使用namespace为空的action
Namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action、/xxx/index.action、或者/xxx/yyy/index.action.
Namespace最好也用模块来进行命名

标签

是用来解决重名的问题,例如当系统的前台和后台都有一个action名叫hello,这时就需要用package来区分。 前台后台
struts2中的package与java的package是相同的作用的

访问Web元素
Action中的会话一般有三种request,session,application,但是他们都是map类型
一般情况下有四种方式可以获得

方法一:ActionContext方式
一般在Action类的构造方法、或execute()方法中获取
如下案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class LoginAction1 extends ActionSupport{
private Map request;
private Map session;
private Map application;
public LoginAction1() {
request=(Map) ActionContext.getContext().get("request");
session=ActionContext.getContext().getSession();
application=ActionContext.getContext().getApplication();
}
@Override
public String execute() throws Exception {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return super.execute();
}

然后在页面中可以通过标签或者java片段取出

1
2
3
<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />
<s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
<s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br/>

方式二:Ioc(控制反转)—推荐使用
让Action类实现RequestAware、SessionAware、ApplicationAware接口,然后重写他们的set方法(setRequest、setSession、setApplication),通过依赖注入、控制反转(原来自己控制,现在由别人来控制值。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}

方式三:获取原类型
获取是的HttpServletRequest/HttpSession/ServletContext

1
2
3
4
5
6
7
8
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public LoginAction3() {
request = ServletActionContext.getRequest();
session = request.getSession();
application = session.getServletContext();
}

一般情况下只用前三种,第四种就不说了

热评文章