0x00 参考

本笔记直接参考或引自如下链接文章:

http://c.biancheng.net/struts2/

https://www.w3cschool.cn/struts_2/

0x01 ResultType简介

ResultType即结果类型。

<results>标签在Struts2 MVC框架中扮演视图的角色。Action负责执行业务逻辑,下一步就是使用<results>标签显示视图。

Struts提供了许多预定义的结果类型,我们已经看到的是默认的结果类型dispatcher,它用于分发到JSP页面。Struts2允许你使用其他标记语言为视图技术呈现结果,较常选用的包括Velocity,Freemaker,XSLT和Tiles。

0x02 配置Result

在 struts.xml 文件中,<result> 元素用于配置 Result 逻辑视图与物理视图之间的映射关系,它有两个可选属性 name 和 type。其中,name 属性用于指定逻辑视图的名称,默认值为 success;type 属性用于指定返回的视图资源的类型,不同的类型代表不同的结果输出,它的默认值是 dispatcher。

struts.xml 文件中的 <result> 元素配置示例代码如下所示:

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

上述代码为 Action 配置了一个 name 为 success 的 Result 映射,该映射的值可以是 JSP 页面,也可以是一个 Action 的 name 值;这里使用 param 子元素为其指定了 Result 映射对应的物理视图资源为 success.jsp。

<param> 子元素的 name 属性有两个值,分别如下:

  • location:指定该逻辑视图所对应的实际视图资源。
  • parse:指定在逻辑视图资源名称中是否可以使用 OGNL(对象图导航语言)表达式。默认值为 true,表示可以使用,如果设为 false,则表示不支持。

其实,上述配置代码还可以简化为如下形式:

1
2
3
<action name="loginAction" class="com.mi1k7ea.LoginAction">
<result>/success.jsp</result>
</action>

需要注意的是,在 Result 配置中指定实际资源位置时,可以使用绝对路径,也可以使用相对路径。

  • 绝对路径以斜杠“/”开头,例如<result>/success.jsp</result>,相当于当前 Web 应用程序的上下文路径。
  • 相对路径不以斜杠“/”开头,例如 <result>success.jsp</result>,相当于当前执行的 Action 路径。

0x03 预定义的ResultType

在使用 Struts2 框架编写项目时,当框架调用 Action 对请求进行处理后,就要向用户呈现一个结果视图。在 Struts2 中,预定义了多种 ResultType(结果类型)展示结果视图。

一个结果类型就是实现了 com.opensymphony.xwork2.Result 接口的类,Struts2 把内置的 <result-type> 都放在 struts-default 包中,struts-default 包就是配置包的父包,这个包定义在 struts2-core-2.3.24.jar 包的根目录下的 struts-default.xml 文件中,在该文件中可以找到相关的 <result-type> 的定义,其代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
<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 属性。class 属性表示这种结果类型的对应类。

Struts2 中预定义的 ResultType 说明如表所示。

属 性 说 明
chain 用于处理 Action 链,被跳转的 Action 中仍能获取上个页面的值,如 request 信息
dispatcher 用于转向页面,通常处理 JSP,是默认的结果类型
freemarker 用于整合 FreeMarker 模板结果类型
httpheader 用于处理特殊的 HTTP 行为结果类型
redirect 重定向到一个 URL,被跳转的页面中丢失传递的信息
redirectAction 重定向到一个 Action,跳转的页面中丢失传递的信息
stream 向浏览器发送 InputStream 对象,通常用于处理文件下载,还可用于 Ajax 数据
velocity 用于整合 Velocity 模板结果类型
xslt 用于整合 XML/XSLT 结果类型
plainText 显示原始文件内容,如文件源代码
postback 使当前请求参数以表单形式提交

表中列举了 Struts2 中预定义的全部 11 种结果类型,其中 dispatcher 是默认的结果类型,主要用于与 JSP 整合。在这全部 11 种结果类型中,dispatcher 和 redirect 是比较常用的结果类型。

需要注意的是,redirect 与 dispatcher 结果类型非常相似,所不同的是 dispatcher 结果类型是将请求转发到 JSP 视图资源,而 redirect 结果类型是将请求重定向到 JSP 视图资源。如果重定向了请求,那么将丢失所有参数,包括 Action 的处理结果。

0x04 dispatcher结果类型

dispatcher 是 Struts2 的默认结果类型,它用于表示转发到指定结果资源。

由于 Struts2 在后台使用 RequestDispatcher 的 forward() 方法转发请求,所以在用户的整个请求/响应过程中,保持的是同一个请求对象,即目标 JSP/Servlet 接收到的请求/响应对象与最初的 JSP/Servlet 的请求/响应对象相同。

dispatcher 结果类型的对应类是 org.apache.struts2.dispatcher.ServletDispatcherResult,该类有 location 和 parse 两个属性,可以通过 struts.xml 配置文件中的 <result> 元素的 <param> 子元素设置,代码如下所示:

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

在上述代码中,location 参数用于指定 Action 执行完毕后要转向的目标资源;parse 参数是一个布尔类型的值,默认是 true,表示解析 location 参数中的 OGNL 表达式,如果为 false,则不解析。

0x05 redirect结果类型

redirect 结果类型用于重定向到指定的结果资源,该资源可以是 JSP 文件,也可以是 Action 类。使用 redirect 结果类型时,系统将调用 HttpServletResponse 的 sendRedirect() 方法将请求重定向到指定的 URL。

redirect 结果类型的对应类是 org.apache.struts2.dispatcher.ServletRedirectResult。在使用 redirect 时,用户要完成一次和服务器之间的交互,浏览器需要发送两次请求,请求过程如图:

使用 redirect 结果类型的工作过程如下。

  1. 浏览器发出一个请求,Struts2框架调用对应的Action实例对请求进行处理。
  2. Action返回success结果字符串,Struts2框架根据这个结果选择对应的结果类型,这里使用的是redirect结果类型。
  3. ServletRedirectResult在内部使用HttpServletResponse的sendRedirect()方法将请求重新定向到目标资源。
  4. 浏览器重新发起一个针对目标资源的新请求。
  5. 目标资源作为响应呈现给用户。

Demo案例参考:http://c.biancheng.net/view/4101.html

0x06 Freemaker结果类型

Freemaker是一个流行的模板引擎,使用预定义的模板生成输出。

Demo

hello.fm,FreeMarker模板文件:

1
This is FreeMarker test, ${name}

HelloWorldAction类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.mi1k7ea.domain;

public class HelloWorldAction{
private String name;

public String execute() throws Exception {
return "success";
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

index.jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World From Struts2</h1>
<form action="hello">
<label for="name">Please enter your name</label><br/>
<input type="text" name="name"/>
<input type="submit" value="Say Hello"/>
</form>
</body>
</html>

配置struts.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
<constant name="struts.devMode" value="true" />
<package name="helloworld" extends="struts-default">

<action name="hello" class="com.mi1k7ea.domain.HelloWorldAction" method="execute">
<result name="success" type="freemarker">
<param name="location">/hello.fm</param>
</result>
</action>

</package>
</struts>

效果如下,看到渲染与JSP视图完全相同,只是我们不绑定使用JSP作为视图技术: