Web笔记-Struts2二

自定义结果视图类型
  • 编写一个类实现Result接口或者继承SturtsResultSupport类
  • 重写doExecute()方法,将原Servlet的逻辑代码写到该方法内
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cn.imeina.struts.result;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.result.StrutsResultSupport;
import com.opensymphony.xwork2.ActionInvocation;
import cn.dsna.util.images.ValidateCode;
public class CaptchaResult extends StrutsResultSupport {
private static final long serialVersionUID = 1L;
private int width = 120;
private int height = 30;
private int codeCount = 4;
private int lineCount = 10;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setCodeCount(int codeCount) {
this.codeCount = codeCount;
}
public void setLineCount(int lineCount) {
this.lineCount = lineCount;
}
//将Servlet中的随机验证码代码写到该方法即可
@Override
protected void doExecute(String arg0, ActionInvocation arg1) throws Exception {
//创建验证码对象
ValidateCode vCode = new ValidateCode(width, height, codeCount, lineCount);
//获取HttpServletResponse对象
HttpServletResponse response = ServletActionContext.getResponse();
//使用指定流输出验证码
vCode.write(response.getOutputStream());
}
}
  • 在struts.xml中申明我们的自定义结果类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<result-types>
<result-type name="captcha" class="cn.imeina.struts.result.CaptchaResult"></result-type>
</result-types>
<!-- 全局视图可服务于当前包下,整个动作。如果在动作配置中找不到对应结果视图,则从全局视图中查找 -->
<global-results>
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
<action name="demo1">
<!-- 局部视图只能服务于当前动作 -->
<result name="success">/success.jsp</result>
</action>
<action name="demo2">
</action>
<action name="captcha">
<result name="success" type="captcha">
<!-- 给结果类型处理类,配置参数 -->
<!-- <param name="width">150</param>
<param name="height">40</param> -->
</result>
</action>
</package>
</struts>
静态参数封装

原理:struts2框架通过一个过滤器staticParams来完成的静态参数注入。

1
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

示例代码:

Action类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cn.imeina.struts.action;
import com.opensymphony.xwork2.ActionSupport;
public class ParamsAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
System.out.println("name=" + name);
return null;
}
}

struts.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<action name="params" class="cn.imeina.struts.action.ParamsAction">
<param name="name">高鹏飞</param>
</action>
</package>
</struts>
动态参数(和实际开发有关)

原理:struts2框架通过一个过滤器params来完成的静态参数注入。

1
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
  • 动作类充当数据模型

示例代码:

DynamicParamsAction.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package cn.imeina.struts.action;
import com.opensymphony.xwork2.ActionSupport;
public class DynamicParamsAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String execute() throws Exception {
System.out.println("姓名:" + name + ",密码:" + password);
return null;
}
}

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div align="center" style="width: 100%; height: 100%">
<form action="${pageContext.request.contextPath}/dynamicParamsAction.action" method="post">
<table border="1" width="auto" height="auto">
<tr>
<td align="right">用户名:</td>
<td><input name="name" type="text" /></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录" /></td>
</tr>
</table>
</form>
</div>
</body>

struts.xml

1
2
3
4
5
6
7
8
9
10
11
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<!-- 动态参数注入 -->
<action name="dynamicParamsAction" class="cn.imeina.struts.action.DynamicParamsAction"></action>
</package>
</struts>
  • 动作类和模型分离

原理:

示例代码:

DynamicParamsAction2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package cn.imeina.struts.action;
import com.opensymphony.xwork2.ActionSupport;
import cn.imeina.struts.domain.User;
public class DynamicParamsAction2 extends ActionSupport {
private static final long serialVersionUID = 1L;
private User user;
public User getUser() {
System.out.println("getUser()...");
return user;
}
public void setUser(User user) {
System.out.println("setUser()...");
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user.toString());
return null;
}
}

动作类与模型分离

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package cn.imeina.struts.domain;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private String password;
public User() {
}
public User(String name, String password) {
super();
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + "]";
}
}

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div align="center" style="width: 100%; height: 100%">
<form action="${pageContext.request.contextPath}/dynamicParamsAction2.action" method="post">
<table border="1" width="auto" height="auto">
<tr>
<td align="right">用户名:</td>
<td><input name="user.name" type="text" /></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input name="user.password" type="password" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录" /></td>
</tr>
</table>
</form>
</div>
</body>

struts.xml

1
2
3
4
5
6
7
8
9
10
11
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<!-- 动态参数注入动作类与实体分离 -->
<action name="dynamicParamsAction2" class="cn.imeina.struts.action.DynamicParamsAction2"></action>
</package>
</struts>
  • 模型驱动(ModeDriver)

原理:struts2框架通过一个过滤器ModeDriver来完成的静态参数注入。

1
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

示例代码:

DynamicParamsAction3.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package cn.imeina.struts.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import cn.imeina.struts.domain.User;
public class DynamicParamsAction3 extends ActionSupport implements ModelDriven<User> {
private static final long serialVersionUID = 1L;
private User user = new User();
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user.toString());
return null;
}
@Override
public User getModel() {
return user;
}
}

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div align="center" style="width: 100%; height: 100%">
<form action="${pageContext.request.contextPath}/dynamicParamsAction3.action" method="post">
<table border="1" width="auto" height="auto">
<tr>
<td align="right">用户名:</td>
<td><input name="name" type="text" /></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input name="password" type="password" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录" /></td>
</tr>
</table>
</form>
</div>
</body>

struts.xml

1
2
3
4
5
6
7
8
9
10
11
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<!-- 模型驱动 -->
<action name="dynamicParamsAction3" class="cn.imeina.struts.action.DynamicParamsAction3"></action>
</package>
</struts>
  • 批量添加数据(配合集合使用)

示例代码:

DynamicParamsAction4.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package cn.imeina.struts.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import cn.imeina.struts.domain.User;
public class DynamicParamsAction4 extends ActionSupport {
private static final long serialVersionUID = 1L;
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@Override
public String execute() throws Exception {
System.out.println(users.toString());
return null;
}
}

multiadd.jsp

1
2
3
4
5
6
7
8
9
10
11
<body>
<form action="${pageContext.request.contextPath}/dynamicParamsAction4" method="post">
用户一:<br>
姓名:<input type="text" name="users[0].name"/> &nbsp;&nbsp;密码:<input type="password" name="users[0].password"/><br>
用户二:<br>
姓名:<input type="text" name="users[1].name"/> &nbsp;&nbsp;密码:<input type="password" name="users[1].password"/><br>
用户三:<br>
姓名:<input type="text" name="users[2].name"/> &nbsp;&nbsp;密码:<input type="password" name="users[2].password"/><br>
<input type="submit" value="提交"/>
</form>
</body>

struts.xml

1
2
3
4
5
6
7
8
9
10
11
<?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 name="struts.devMode" value="true" />
<package name="p1" extends="struts-default">
<!-- 批量添加 -->
<action name="dynamicParamsAction4" class="cn.imeina.struts.action.DynamicParamsAction4"></action>
</package>
</struts>
数据类型转换
  • struts2中的数据类型转换简介
  1. 日期:在struts2会自动按照本地计算机的日期进行转换。

  2. 日期转换失败:框架会自动转向一个name为input的视图。

  • 自定义类型转换器

实验目的:本地日期格式yyyy-MM-dd,要求输入19920811后可转换成功。

了解Struts2中的类型转换有关核心类

struts2类型转换类结构图

结论:

  1. 编写自定义类型转换器,继承DefaultTypeConverter类,并覆盖convertValue()方法。

  2. 编写自定义类型转换器,继承StrutsTypeConverter,完成String转其他类型,其他类型转String。

示例代码:

继承DefaultTypeConverter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package cn.imeina.struts.convertors;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
/**
* 自定义日期类型转换器
* @author gaopengfei
* yyyyMMdd-->Date
* Date-->yyyyMMdd
*/
public class MyDateConverter1 extends DefaultTypeConverter {
/**
* 类型转换:双向转换
* Object:返回值。
* String-->其他类型,Object就是其他类型。
* 其他类型-->String,Object就是String类型。
*
* 参数:
* Object value
* 用户封装数据-->JavaBean:value是String[]
* 显示数据:value就是其他类型数据
*
* Class toType
* 用户封装数据-->toType就是目标类型
* 显示数据:toType就是String类型
*/
@Override
public Object convertValue(Object value, Class toType) {
if (value == null) {
//数据为null
return null;
}
DateFormat format = new SimpleDateFormat("yyyyMMdd");
if (toType == String.class) {
//目标类型转String
Date date = (Date)value;
return format.format(date);
}else {
//String转目标类型
String[] values = (String[]) value;
if (values == null || values.length == 0) {
return null;
}
String dateValue = values[0];
try {
Date date = format.parse(dateValue);
System.out.println("日期转换后:" + date);
return date;
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
}
}

继承StrutsTypeConverter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package cn.imeina.struts.convertors;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class MyDateConverter2 extends StrutsTypeConverter {
private DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
/**
* 将String类型转为其他类型
*/
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
if (values == null || values.length == 0) {
return null;
}
String date = values[0];
try {
return format.parseObject(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 将其他类型转为String类型
*/
@Override
public String convertToString(Map context, Object o) {
return null;
}
}
  • 注册类型转换器
  1. 局部类型转换器:按照属性名称进行注册。

局部类型转换器代码结构

最主要的局部类型转换,需要在实体类的目录下创建xxx-conversion.properties配置文件,文件中将需要转换的属性名作为键,值为自定义转换器的类的全路径

  1. 全局类型转换器:按照目标类型进行注册。

全局类型转换器代码结构

与局部类型转换器相似,只是需要在src根目录下创建xwork-conversion.properties配置文件,其键为目标转换类型全类名,值为自定义转换器类的全路径,其他配置相同

  1. 类型转换失败

前面提到若struts框架转换数据出错时,框架会自动转向一个name为input的视图。通常情况下我们定义一个input的结果视图,将结果指给当前页。

如何在页面类型出错后input视图转回当前页面后,能回显先前填写的信息呢?

使用el表达式,struts会自动记录先前提交失败的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<div align="center" style="width: 100%; height: 100%">
<form action="${pageContext.request.contextPath}/regist.action" method="post">
<table border="1" width="auto" height="auto">
<tr>
<td align="right">用户名:</td>
<td><input name="user.userName" type="text" value="${user.userName}"/></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input name="user.password" type="password" value="${user.password}"/></td>
</tr>
<tr>
<td align="right">昵称:</td>
<td><input name="user.nickName" type="text" value="${user.nickName}"/></td>
</tr>
<tr>
<td>出生日期:</td>
<td><input name="user.birthday" type="text" value="${user.birthday}"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="注册" /></td>
</tr>
</table>
</form>
</div>
</body>

如何利用struts框架自身的验证来实现一个友好的提示?

页面引入struts标签库,使用即可

1
2
3
4
<!-- 引入struts标签库 -->
<%@ taglib uri="/struts-tags" prefix="s" %>
<!-- 使用标签 -->
<s:fielderror></s:fielderror>

struts默认字段类型转换错误提示

默认错误提示为英文,我们可以使用struts的i18n进行字段错误提示信息的国际化处理

步骤:

在所在字段的实体类包下创建实体类_zh_CN.properties(例如:User_zh_CN.properties)配置文件。

配置代码:

1
2
invalid.fieldvalue.birthday=\u65E5\u671F\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
<!--invalid.fieldvalue.-->为固定代码,后接具体字段名称,值为自己指定的信息提示

struts字段类型错误提示i18n

说明:struts的错误回显是由conversionError拦截器所拦截处理。所有错误信息都会存放到Map中(key:错误字段名,value:错误信息)。拦截器如果发现Map中有元素,则说明转换失败,自动转向action=”input”视图,如果Map为空,则转换无误。

conversionError位于struts-default.xml中:

1
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
如果帮到了你,想打赏支持,喏~