1.表单一般使用struts2标签<s:form validate="false"/>关闭客户端验证,使用<s:textfield type="text" name="name"/>name对应action中的属性
2.在Action配置中一定要设置input返回页面<result name="input"/>
3.添加验证只要创建验证的xml文件,在Action同包下,创建:Action类名-validation.xml
4.对于int型和Date型如果客户端传来的格式不对,后台会提示警告报错,需要用javascript正则表达式验证。
- <!DOCTYPE validators PUBLIC
- "-//Apache Struts//XWork Validator 1.0.2//EN"
- "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
- <validators>
- <field name="name">
- <field-validator type="requiredstring">
- <param name="trim">true</param>
- <message>请填写用户名</message>
- </field-validator>
- <field-validator type="stringlength">
- <param name="minLength">4</param>
- <param name="maxLength">32</param>
- <message>用户名长度应在4到32个字符间</message>
- </field-validator>
- </field>
- <field name="pass">
- <field-validator type="requiredstring">
- <message>请填写密码</message>
- </field-validator>
- <field-validator type="stringlength">
- <param name="minLength">6</param>
- <param name="maxLength">32</param>
- <message>为了您账号的安全,请设置6个字母以上的密码(最长可设置32个字母)</message>
- </field-validator>
- </field>
- <field name="age">
- <field-validator type="int">
- <param name="min">1</param>
- <param name="max">70</param>
- <message>请输入1-70之间</message>
- </field-validator>
- </field>
- <field name="birth">
- <field-validator type="date">
- <param name="min">1900-01-01</param>
- <param name="max">2050-02-21</param>
- <message>生日必须在{min}到{max}之间</message>
- </field-validator>
- </field>
- </validators>
1,输入校验介绍
Struts2提供了功能强大的输入校验机制,通过Struts2内建的输入校验器,应用无需书写任何代码,即可完成大部分的校验功能,并可以同时完成客户端和服务器端的校验。如果应用的输入校验规则特别,Struts2也允许通过重写validate方法来完成自定义校验,另外Struts2的开放性还允许开发者提供自定义的校验器。
表现层的数据处理包括两个方面:一是数据类型的转化,因为Web应用接收到的所有数据都是字符串类型的;另一个就是输入校验,因为开发者必须全面考虑用户输入的各种情况,尤其需要注意那些非正常输入。
客户端的校验最基础的方法就是在页面写javascript代码手工校验,服务器端的校验最基础的方法就是在处理请求的Servlet的service()方法中添加校验代码。
Struts2中可以通过重写validate方法来完成输入校验。如果我们重写了validate方法,则该方法会应用于此Action中的所有提供服务的业务方法。Struts2支持校验特定方法的validateXxx()方法。例如某个Action中有一个regist()业务方法,我们可以写一个validateRegist()方法来进行regist()的特殊校验,客户端请求调用的次序如下:validateRegist()--------------->validate()-------------->regist()
Struts2的输入校验流程如下:
1,类型转换器负责对字符串的请求参数执行类型转换,并将这此值设置成Action的属性值。
2,在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,conversionError拦截器负责将其封装到fieldError里,然后执行第3步;如果转换过程没有异常信息,则直接进入第3步。
3,通过反射调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名。
4,调用Action类里的validate()方法。
5,如果经过上面4步都没有出现fieldError,将调用Action里处理用户请求的处理方法;如果出现了fieldError,系统将转入input逻辑视图所指定的视图资源。
2,Struts2的输入校验
1,最基础的Struts2输入校验
Struts2中单独对每一个Action指定一个校验文件,它的命名方式为<Action-name>-validation.xml。它存放在与Action相同的包中,校验只需要配置一个校验文件即可实现。系统的其它地方不需要改动,系统会自动加载该文件。校验文件RegistAction-validation.xml如下例:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<!-- 校验文件的根元素 -->
<validators>
<!-- 校验Action的name属性 -->
<field name="name">
<!-- 指定name属性必须满足必填规则 -->
<field-validator type="requiredstring">
<!-- 校验前去掉name属性的前后空格 -->
<param name="trim">true</param>
<!-- 提示信息 -->
<message>必须输入名字</message>
</field-validator>
<!-- 指定name属性必须满足匹配指定的正则表达式 -->
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>您输入的用户名只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="pass">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入密码</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>您输入的密码只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="age">
<!-- 指定age属性必须在指定的范围内 -->
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年纪必须在1到150之间</message>
</field-validator>
</field>
<field name="birth">
<!-- 指定age属性必须在指定的范围内 -->
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>年纪必须在${min}到${max}之间</message>
</field-validator>
</field>
</validators>
2,Struts2中输入校验提示信息的国际化
在Struts2的校验中应用国际化也非常简单,请看如下xml配置代码: <field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="name.requried"/>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message key="name.regex"/>
</field-validator>
</field>
message元素指定key属性指定的是国际化资源中对应的key。还可以使用以下配置获取国际化资源中的信息:<message>${getText("name.requried")}</message> 这种方式是通过调用ActionSupport类的getText()方法来获取国际化资源的。
3,Struts2中应用客户端输入校验
使用客户端输入校验可以减轻服务器的负担。Struts2对客户端的输入校验进行了封装,使得我们开发时特别容易。
1,JSP页面代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>注册页面</title>
</head>
<body>
<s:form action="regist" validate="true">
<s:textfield label="用户名" name="name"></s:textfield>
<s:password label="密码" name="pass"></s:password>
<s:textfield label="年龄" name="age"></s:textfield>
<s:textfield label="生日" name="birth"></s:textfield>
<s:submit></s:submit>
</s:form>
</body>
</html>
注意这里要用Struts2的标签,form的validate属性要设置为true,并且不要将theme属性指定为simple.(simple表示struts2将把这个解析成普通的HTML标签)
2,校验配置文件:这里的校验配置文件同原先的配置文件并没有不同,但是这里使用<message key="name.requried"/>无法从全局国际化资源中获取信息,只能使用<message>${getText("name.requried")}</message>方式获取国际化资源。
3,部署后的JSP页面代码:
大家可以看到部署后的JSP页面中自动生成了我们在校验配置文件中对应的javascript代码。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>注册页面</title>
</head>
<body>
<script src="/lovely/struts/xhtml/validation.js"></script>
<form namespace="" id="regist" name="regist" οnsubmit="return validateForm_regist();"action="/lovely/regist.action" method="POST">
<table class="wwFormTable">
<tr>
<td class="tdLabel"><label for="regist_name" class="label">用户名:</label></td>
<td
><input type="text" name="name" value="" id="regist_name"/>
</td>
</tr>
<tr>
<td class="tdLabel"><label for="regist_pass" class="label">密码:</label></td>
<td
><input type="password" name="pass" id="regist_pass"/>
</td>
</tr>
<tr>
<td class="tdLabel"><label for="regist_age" class="label">年龄:</label></td>
<td
><input type="text" name="age" value="" id="regist_age"/>
</td>
</tr>
<tr>
<td class="tdLabel"><label for="regist_birth" class="label">生日:</label></td>
<td
><input type="text" name="birth" value="" id="regist_birth"/>
</td>
</tr>
<tr>
<td colspan="2"><div align="right"><input type="submit" id="regist_0" value="Submit"/>
</div></td>
</tr>
</table></form>
<script type="text/javascript">
function validateForm_regist() {
form = document.getElementById("regist");
clearErrorMessages(form);
clearErrorLabels(form);
var errors = false;
// field name: name
// validator name: requiredstring
if (form.elements['name']) {
field = form.elements['name'];
var error = "必须输入用户名!";
if (field.value != null && (field.value == "" || field.value.replace(/^/s+|/s+$/g,"").length == 0)) {
addError(field, error);
errors = true;
}
}
// field name: name
// validator name: regex
if (form.elements['name']) {
field = form.elements['name'];
var error = "您输入的用户名只能是字母和数组,且长度必须在4到25之间";
if (field.value != null && !field.value.match("(//w{4,25})")) {
addError(field, error);
errors = true;
}
}
// field name: pass
// validator name: requiredstring
if (form.elements['pass']) {
field = form.elements['pass'];
var error = "必须输入密码";
if (field.value != null && (field.value == "" || field.value.replace(/^/s+|/s+$/g,"").length == 0)) {
addError(field, error);
errors = true;
}
}
// field name: pass
// validator name: regex
if (form.elements['pass']) {
field = form.elements['pass'];
var error = "您输入的密码只能是字母和数组,且长度必须在4到25之间";
if (field.value != null && !field.value.match("(//w{4,25})")) {
addError(field, error);
errors = true;
}
}
// field name: age
// validator name: int
if (form.elements['age']) {
field = form.elements['age'];
var error = "年纪必须在1到150之间";
if (field.value != null) {
if (parseInt(field.value) <
1 ||
parseInt(field.value) >
150) {
addError(field, error);
errors = true;
}
}
}
// field name: birth
// validator name: date
if (form.elements['birth']) {
field = form.elements['birth'];
var error = "年纪必须在00-1-1到50-2-21之间";
}
return !errors;
}
</script>
</body>
</html>
从上面Struts2自动生成的javascript代码可以看到,最后的birth校验并没有按照我们要求的来校验,可见Struts2中并不是所有的服务器端校验都可以转换成客户端校验。客户端校验仅仅支持如下几种校验器:
required validator 必填校验器
requiredstring validator 必填字符串校验器
stringlength validator 字符串长度校验器
regex validator 表达式校验器
email validator 邮件校验器
url validator 网址校验器
int validator 整数校验器
double validator 双精度数校验器
4,为指定的方法配置特殊的校验规则
当一个Action中有多个业务方法时,我们可能需要对其中的某个方法配置单独的校验规则,比如注册时的要求用户两次输入的密码必须相同等,这时我们可以配置一个单独的校验文件,命名规则为:<actionName>-<methodName>-validation.xml,可以看到这里多了一个方法名,这个方法名就是要校验的业务逻辑在struts.xml配置文件中配置的name,这个文件也要同Action放在同一个目录下。
5,多个校验规则文件的搜索次序
例如有一个LoginAction继承BaseAction,这两个Action中都有业务方法login,并且存在4份校验规则文件如下:BaseAction-vadition.xml, BaseAction-login-validation.xml , LoginAction-validation.xml, LoginAction-login-validation.xml那么用户访问LoginAction的login方法里,会按照以上的顺序执行校验规则,实际的校验规则是以上四个校验规则的总和,但是如果存在冲突的情况下,后面的校验规则优先。
6,非字段校验器的配置
Struts2中除了有象我们的配置文件的那种以字段为基础的校验文件的配置外,还有另外一种以校验规则为基础的配置,请看下面的配置文件的代码:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<!-- 配置指定必填字符串的校验器 -->
<validator type="requiredstring">
<!-- 要校验的属性为name -->
<param name="fieldName">name</param>
<!-- 其它参数 -->
<param name="trim">true</param>
<!-- 返回的提示 -->
<message>${getText("name.requried")}</message>
</validator>
<validator type="regex">
<param name="fieldName">name</param>
<param name="trim">true</param>
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>${getText("name.regex")}</message>
</validator>
<validator type="requiredstring">
<param name="fieldName">pass</param>
<param name="trim">true</param>
<message>${getText("pass.requried")}</message>
</validator>
<validator type="regex">
<param name="fieldName">pass</param>
<param name="trim">true</param>
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>${getText("pass.regex")}</message>
</validator>
<validator type="int">
<param name="fieldName">age</param>
<param name="min">1</param>
<param name="max">150</param>
<message>${getText("age.range")}</message>
</validator>
<validator type="date">
<param name="fieldName">birth</param>
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>${getText("birth.range")}</message>
</validator>
</validators>
7,短路校验器的配置
Struts2默认的校验配置是非短路的方式,即把一个字段所有的不符合要求的提示都提示用户,我们也可以配置以短路的方式提示用户,即当用户输入的条件不满足第一次校验的时候就返回提示信息,不再往下执行。这种配置方式只能是以字段为基础的校验器。只需要在<field-validator>元素上加上short-circuit="true"即可,例如:
<field name="name">
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<message>${getText("name.requried")}</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>${getText("name.regex")}</message>
</field-validator>
</field>
这种方式可能会造成多次提示用户,所以并不推荐使用此方式,并且客户端校验并不支持这种方式。并且采用这种方式之后,校验的顺序将很难控制(主要是按照规则来进行控制,但此时将花费大量时间)。
3,Struts2的内建校验器的介绍
Struts2已经为我们准备了一些内建校验器,我们可以直接使用它们,可以打开Struts2的lib包下的xwork.jar包,在com/opensymphony/xwork2/validator/validators/default.xml文件中,我们可以看到Struts2的内建校验器。我们也可以开发自己的校验器。方法如下:添加一个validators.xml文件在WEB/INF/classes目录下,validators.xml文件中的配置则同刚才说的Struts2的内建校验器的配置相同。再开发出自己的校验器类,在validators.xml中注册就可以了。如果在WEB-INF/classes目录添加了文件validators.xml文件,则Struts2不会再应用默认的校验器,因此这时需要将default.xml文件中的所有校验器都复制到validators.xml文件中。
从Struts2的配置文件中可以看到Struts2有如下内建校验器:
1,required 必填校验器,要求字段必须有值
2,requiredstring 必填字符串校验器,要求必须有值且长度大于0,即不能是空字符串。默认会去掉字符串前后空格
3,int 整数校验器,可以配置整数在指定的范围内
4,double 双精度校验器,可以配置双精度数在指定的范围内
5,date 日期校验器,可以配置日期在指定的范围内
6,expression 表达式校验器,它是一个非字段校验器,当参数expression计算的值为true时,校验通过,否则返回提示。
7,fieldexpression 字段表达式校验器,当参数expression计算的值为true时,校验通过,否则返回提示。它和6一样多用于在用户的两次输入中间进行判断,如下例:
<!-- 要校验的属性为rpass -->
<field name="rpass">
<!-- 使用fieldexpression校验器 -->
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[(rpass == password)]]></param>
<message>两次密码不相同!</message>
</field-validator>
</field>
7,email 邮件地址校验器,要求被检查的字段如果非空,则必须是合法的邮件地址。
8,url 网址校验器,要求被检查的字段如果非空,则必须是合法的URL地址。7和8都是基于正则表达式来计算的,可能会随着技术的进步而不同,用户可以自己扩展。
9,visitor Visitor校验器,用于检测Action里的复合属性。例如:RegistAction中包含了一个User属性,那么要校验User里的属性就要使用Visitor校验器,RegistAction-validation.xml文件中的配置如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<!-- 指定校验user属性 -->
<field name="user">
<!-- 使用visitor校验器 -->
<field-validator type="visitor">
<!-- 指定校验规则文件的context -->
<param name="context">userContext</param>
<!-- 指定校验失败后的提示信息是否添加下面的前缀 -->
<param name="appendPrefix">true</param>
<!-- 指定校验失败的提示信息的前缀 -->
<message>用户的:</message>
</field-validator>
</field>
</validators>
还要另外再为User属性配置单独的校验文件,默认的文件名应为User-validation.xml,因为刚在在RegistAction-validation.xml文件中指定了visitor的context属性为userContext,因此校验文件名应为:User-userContext-validation.xml,该文件同一般的校验文件一样,代码如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入名字</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>您输入的用户名只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="pass">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入密码</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>您输入的密码只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年纪必须在1到150之间</message>
</field-validator>
</field>
<field name="birth">
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>年纪必须在${min}到${max}之间</message>
</field-validator>
</field>
</validators>
当然这时候的JSP页面中也与之前的不一样,它要把页面属性直接赋值给Action中的User中的属性,这在之前的几课中已经有过说明,页面代码如下:
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>请输入您的注册信息</title>
</head>
<body>
<H1>请输入您的注册信息</H1>
<s:fielderror/>
<FORM METHOD="POST" ACTION="regist.action">
用户名:<INPUT TYPE="text" NAME="user.name"><br>
密 码:<INPUT TYPE="text" NAME="user.pass"><br>
年 龄:<INPUT TYPE="text" NAME="user.age"><br>
生 日:<INPUT TYPE="text" NAME="user.birth"><p>
<INPUT TYPE="submit" value="注册">
</FORM>
</body>
</html>
10,conversion 转换校验器,它检查被校验字段在类型转换过程中是否出现错误。例子如下:
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年纪必须在1到150之间</message>
</field-validator>
<field-validator type="conversion">
<!-- 指定类型转换失败后,返回输入页面依然保留原来的错误输入 -->
<param name="repopulateField">true</param>
<!-- 转换失败后的提示信息 -->
<message>你的年龄必须是一个整数</message>
</field-validator>
</field>
11,stringlength 字符串长度校验器,它要求被校验的字段长度必须在指定的范围内,否则校验失败。例:
<field name="pass">
<field-validator type="stringlength">
<param name="minLength">4</param>
<param name="maxLength">10</param>
<message>长度必须在4-10之间</message>
</field-validator>
</field>
12,regex 正则表达式校验器,它检查被校验的字段是否匹配指定的正则表达式,例:
<field name="pass">
<field-validator type="regex">
<param name="expression"><![CDATA[(/w{4,25})]]></param>
<message>您输入的密码只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
自定义拦截器验证
要自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口:
- public class PermissionInterceptor implements Interceptor {
- private static final long serialVersionUID = -5178310397732210602L;
- public void destroy() {
- }
- public void init() {
- }
- public String intercept(ActionInvocation invocation) throws Exception {
- System.out.println("进入拦截器");
- if(session里存在用户){
- String result = invocation.invoke();
- }else{
- return “logon”;
- }
- //System.out.println("返回值:"+ result);
- //return result;
- }
- }
- <package name="csdn" namespace="/test" extends="struts-default">
- <interceptors>
- <interceptor name=“permission" class="cn.csdn.aop.PermissionInterceptor" />
- <interceptor-stack name="permissionStack">
- <interceptor-ref name="defaultStack" />
- <interceptor-ref name=" permission " />
- </interceptor-stack>
- </interceptors>
- <action name="helloworld_*" class="cn.csdn.action.HelloWorldAction" method="{1}">
- <result name="success">/WEB-INF/page/hello.jsp</result>
- <interceptor-ref name="permissionStack"/>
- </action>
- </package>
因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。
输入校验
在struts2中,我们可以实现对action的所有方法进行校验或者对action的指定方法进行校验。
对于输入校验struts2提供了两种实现方法:
1. 采用手工编写代码实现。
2. 基于XML配置方式实现。
手工编写代码实现对action中所有方法输入校验
通过重写validate() 方法实现, validate()方法会校验action中所有与execute方法签名相同的方法。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。
validate()使用例子:
- public void validate() {
- if(this.mobile==null || "".equals(this.mobile.trim())){ this.addFieldError("username", "手机号不能为空");
- }else{ if(!Pattern.compile("^1[358]\\d{9}").matcher(this.mobile.trim()).matches()){
- this.addFieldError(“mobile", "手机号的格式不正确"); }
- }
- }
另一个:
- public void validate() {
- List<String> args = new ArrayList<String>();
- args.add("chrp");
- args.add("红豆");
- System.out.println(getText("wel",args));
- System.out.println(getText("wel", new String[]{"deep","朋友网!"}));
- System.out.println(getText("nameerror"));
- if ("".equals(name) || this.name == null) {
- addFieldError("name", getText("nameerror"));
- }
- }
验证失败后,请求转发至input视图:
<result name="input">/WEB-INF/page/addUser.jsp</result>
在addUser.jsp页面中使用<s:fielderror/>显示失败信息。
手工编写代码实现对action指定方法输入校验
通过validateXxx()方法实现, validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。
validateXxx()方法使用例子:
- public String add() throws Exception{ return "success";}
- public void validateAdd(){
- if(username==null && "".equals(username.trim())) this.addFieldError("username", "用户名不能为空");
- }
验证失败后,请求转发至input视图:
<result name="input">/WEB-INF/page/addUser.jsp</result>
在addUser.jsp页面中使用<s:fielderror/>显示失败信息。
输入校验的流程
1、类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
2、如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息添加到fieldErrors里。不管类型转换是否出现异常,都会进入第3步。
3、系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
4、再调用action中的validate()方法。
5、经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
基于XML配置方式实现对action的所有方法进行输入校验
使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName为action的简单类名,-validation为固定写法。如果Action类为cn.csdn.UserAction,那么该文件的取名应为:UserAction-validation.xml。下面是校验文件的模版:
- <?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>
- </validators>
<field>指定action中要校验的属性,<field-validator>指定校验器,上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求的校验器,这些校验器的定义可以在xwork-2.x.jar中的com.opensymphony.xwork2.validator.validators下的default.xml中找到。
<message>为校验失败后的提示信息,如果需要国际化,可以为message指定key属性,key的值为资源文件中的key。
在这个校验文件中,对action中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断用户名是否为空。
struts2提供的校验器列表
系统提供的校验器如下:
required (必填校验器,要求field的值不能为null)
requiredstring (必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength(字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex(正则表达式校验器,检查被校验的field是否匹配一个正则表达式.expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email(邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地址)
url(网址校验器,要求如果field的值非空,则必须是合法的url地址)
date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion(转换校验器,指定在类型转换失败时,提示的错误信息)
visitor(用于校验action中的复合属性,它指定一个校验文件用于校验复合属性中的属性)
expression(OGNL表达式校验器,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)
校验器的使用例子
- required 必填校验器
- <field-validator type="required">
- <message>性别不能为空!</message>
- </field-validator>
- requiredstring 必填字符串校验器
- <field-validator type="requiredstring">
- <param name="trim">true</param>
- <message>用户名不能为空!</message>
- </field-validator>
- stringlength:字符串长度校验器
- <field-validator type="stringlength">
- <param name="maxLength">10</param>
- <param name="minLength">2</param>
- <param name="trim">true</param>
- <message><![CDATA[产品名称应在2-10个字符之间]]></message>
- </field-validator>
- email:邮件地址校验器
- <field-validator type="email">
- <message>电子邮件地址无效</message>
- </field-validator>
- regex:正则表达式校验器
- <field-validator type="regex">
- <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
- <message>手机号格式不正确!</message>
- </field-validator>
- int:整数校验器
- <field-validator type="int">
- <param name="min">1</param>
- <param name="max">150</param>
- <message>年龄必须在1-150之间</message>
- </field-validator>
- 字段OGNL表达式校验器
- <field name="imagefile">
- <field-validator type="fieldexpression">
- <param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
- <message>文件不能为空</message>
- </field-validator>
- </field>
基于XML配置方式对指定action方法实现输入校验
当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。例如:在实际应用中,常有以下配置:
<action name="user_*" class="cn.csdn.action.UserAction" method="{1}“ >
<result name="success">/WEB-INF/page/message.jsp</result>
<result name="input">/WEB-INF/page/addUser.jsp</result>
</action>
UserAction中有以下两个处理方法:
public String add() throws Exception{
....
}
public String update() throws Exception{
....
}
要对add()方法实施验证,校验文件的取名为: UserAction-user_add-validation.xml
要对update()方法实施验证,校验文件的取名为: UserAction-user_update-validation.xml
基于XML校验的一些特点
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。
假设UserAction继承BaseAction:
<action name="user" class="cn.csdn.action.UserAction" method="{1}">
</action>
访问上面action,系统先搜索父类的校验文件:BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索子类的校验文件: UserAction-validation.xml, UserAction-user-validation.xml。应用于上面action的校验规则为这四个文件的总和。