struts2学习5:输入校验
struts2提供了功能强大的输入校验机制,通过struts2内建的输入校验器,可完成大部分的校验功能,并可以同时完成客户端和服务器端的校验。如果应用的输入校验规则特别,struts2也允许通过重写validate方法来完成自定义校验。
输入校验的流程
- 类型转换器对输入参数进行类型转换,并把转换后的值赋给action中的属性。
- 如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器会将异常信息添加到fieldErrors里,不管是否出现异常,都会进入第三步。
- 系统通过反射技术先调用action中的validateXxx()方法,
- 然后在调用validate()方法。
- 最后,如果系统的fieldErrors中存在错误信息(*即存放错误信息的集合的size大于0),系统会将请求回发到input视图中,如果没有错误信息,系统会执行action中的处理方法。
在struts2中,我们可以实现对Action的所有方法进行校验,也可以对Action中的指定方法进行校验。
对于输入校验struts2提供了两种方法:手工编写代码实现、基于XML配置方法实现。
手工编写代码实现
对Action中所有方法进行校验
举例:实现对用户名和手机号进行输入校验
输入界面index.jsp代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>输入校验</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<s:fielderror/>
<form action="${pageContext.request.contextPath}/person/manage_update.action" method="post">
用户名:<input type="text" name="username"/>不能为空<br/>
手机号:<input type="text" name="mobile"/>不能为空,并且要符合手机号的格式1,3/5/8,后面是9个数字<br/>
<input type="submit" value="提交"/></form>
</body>
</html>
struts.xml配置文件如下:1
2
3
4
5
6
7
8<struts>
<package name="person" namespace="/person" extends="struts-default">
<action name="manage_*" class="cn.zju.struts.PersonAction" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
接下来就是重头戏,手动编写的校验类,继承类ActionSupport,重新validate方法。在validate()方法中对表单界面传过来的数据进行校验。当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加校验失败信息。当最后系统的fieldErrors包含失败信息时,struts2会将请求转发到名为”input”的result中,在”input”视图中可以通过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
41public class PersonAction extends ActionSupport{
private String username;
private String mobile;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String update(){
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save(){
ActionContext.getContext().put("message", "保存成功");
return "message";
}
@Override
public void validate() { //会对action中的所有方法校验
if(this.username==null || "".equals(this.username.trim())){
this.addFieldError("username", "用户名不能为空");
}
if(this.mobile==null || "".equals(this.mobile.trim())){
this.addFieldError("mobile", "手机号不能为空");
}else{
if(!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()){
this.addFieldError("mobile", "手机号格式不正确");
}
}
}
}
对Action中指定方法进行校验
对Action中指定方法进行校验时和上面的流程一样,唯一却别在于:对Action中所有方法进行校验时,需要实现validate()方法,而对指定方法进行校验时,通过validateXxx()实现,validateXxx()只会校验Action中方法名为Xxx的方法,其中Xxx第一个字母要大写。
基于XML配置方式实现校验
对Action中所有方法进行校验
基于XML培植物文件校验时,Action仍需继承ActionSupport,但不需要我们手动编写任何校验方法,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
25
26
27public class PersonAction extends ActionSupport{
private String username;
private String mobile;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String update(){
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save(){
ActionContext.getContext().put("message", "保存成功");
return "message";
}
}
我们需要提供校验文件,校验文件和Action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,对于本例就是PersonActione-validation.xml,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手机号不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
</field>
</validators>
对Action中指定方法进行校验
当校验文件取名为ActionClassName-validation.xml时,会对Action中所有的方法进行校验,当只需要对Action中某个方法进行校验时,那么文件应该取名ActionClassName-ActionName-validation.xml,举例:有以下配置文件:1
2
3
4
5
6
7
8<struts>
<package name="person" namespace="/person" extends="struts-default">
<action name="manage_*" class="cn.zju.struts.PersonAction" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
在PersonAction有两个处理方法:1
2
3
4
5
6
7
8
9public String update(){
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save(){
ActionContext.getContext().put("message", "保存成功");
return "message";
}
因此,要对update()方法进行验证,校验文件取名为:PersonAction-manage_update-validation.xml
基于XML校验的一些特点
当为某一个Action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件是,系统会按照下面顺序寻找校验文件:
- ActionClassName-validation.xml
- ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有的校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于Action方法的校验。如果两个校验文件中指定的校验规则有冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会优先搜索到。