1、验证方式有两种:
(1)声明式验证
(2)编程式验证
2、配置步骤
(1)确认需要验证的字段名
(2)编写配置文件
I、当一个action类的多个action使用相同验证规则,在当前action所在包下新建 actionClassName-validation.xml
II、当一个action类的多个action使用不同验证规则,在当前action所在包下新建actionClassName-actionName-validation.xml(1)把xml的头设置为xwork validation的头
(2)用validators标签包着准备编写的规则
(3)参照以下地址的验证字段说明,编写验证规则:https://struts.apache.org/core-developers/validation.html
(4)对错误消息进行国际化,即field标签中的message内容国际化
(3)国际化错误信息配置
(1)在struts.xml配置国际化资源文件的constant
(2)在action-validation.xml中,把验证的message标签写成 用key关联国际化资源文件的字段名的形式,字段值可以包含 验证规则值的内容如:整型验证中国际化文件 验 证 规 则 值 的 内 容 如 : 整 型 验 证 中 国 际 化 文 件 {fieldName} min m i n {max} 分别动态的读取到配置文件中的字段名、最小值、最大值,使得错误信息可以适配多个不同字段的相同验证规则的响应消息
(3)如果在国际化资源文件中适用多个字段的验证规则使用的提示信息里面的${}中再配置对应字段内容时,可以使用$ {get Text(fieldName)}如:error.int里面的第一个${}需要按照调用error.int的字段来分别读入age或者age2内容时
配置内容:
error.int=${get Text(fieldName)} needs to be between 1 and 10
age=Age
age2=Age2
读取结果:
I、age字段调用error.int显示提示信息结果为:Age needs to be between 1 and 10
II、age2字段调用error.int显示提示信息结果为:Age2 needs to be between 1 and 10
(4)确定验证失败时的响应页面
(1)配置strut.xml中验证失败的result,result的name必须为input 如:
<result name="result">/xxx.jsp</result>
(2)页面显示错误信息如form使用非simole主题,页面会自动显示
如form使用非simple主题,则需要用 s:fielderror fieldName=”字段名”标签或者${fieldErrors.字段名[0]}显示错误
用s:fielderror标签显示错误时,如果有多个错误信息,则会一次性全部都显示到页面
3、注意事项:
(1)如果一个action类的多个action使用不同验证规则,这些需要对应不同action新建对应的actionClassName-actionName-validation.xml
(2)不带action名的配置文件 actionClassName-validation.xml的验证规则不管什么情况都会运行的,所以不是公用的验证规则不要写到actionClassName-validation.xml里面
4、声明式验证运行原理:
(1)struts2默认拦截器栈中提供了一个validation拦截器
(2)每个验证规则都会对应一个验证器,具体可以看xwork-core-x.x.xx.x.jar的如下文件:com.opensymphony.xwork2.validator.validators包里面的default.xml
5、短路验证:
(1)在actionClassName-validation.xml或者ClassName-actionName-validation.xml中的validator标签或者field-validator标签里面配置,默认false
(2)关键字:short-circuit
(3)一个字段使用多个验证器时,默认按顺序执行该字段已配置的所有验证,如果希望前一个验证不通过时候,后面的验证都不执行,就需要使用短路验证了
6、类型转换失败,直接获得错误信息,不再执行后续验证拦截器
(1)如果action在param拦截器中的ConversionErrorInterceptor拦截器里面就已经发现类型转换错误,希望直接输出错误信息而不继续去执行验证拦截器时,就应该按照下面注意事项2的步骤重写ConversionErrorInterceptor类,使得程序在ConversionErrorInterceptor拦截器得到运行返回结果后停止运行并返回结果到值栈中的错误信息参数中
7、类型转换出错时,重新定义错误显示,统一错误信息
(1)找到xwork-core-x.x.xx.x.jar里面的com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor类
(2)在src下新建com.opensymphony.xwork2.interceptor包,并且重写ConversionErrorInterceptor
(3)验证拦截器是在ConversionErrorInterceptor拦截器之后运行的,就是说struts2会先检查类型转换或数据类型,然后就会去运行验证拦截器,如果出现数据类型出错,而且验证拦截器也验证数据类型的情况,页面就会分别从ConversionErrorInterceptor拦截器和验证拦截器获得各自的数据类型出错的错误信息
(4)为了避免ConversionErrorInterceptor拦截器和验证拦截器的错误信息不统一,和无意义地多运行一次数据类型验证拦截器,所以要重写ConversionErrorInterceptor中对当前调用action判断出错的语句(见ConversionErrorInterceptor。java的139-147行),可以达到,如果类型转换出问题时,不用通过运行验证拦截器多进行一次数据类新验证,直接根据ConversionErrorInterceptor拦截器的结果就输出类型转换的错误就可以了
8、非字段验证:
(1)不是特定某个字段的验证
(2)需要在validators里面新建一个type为expression的validator标签
(3)在param name为expression的标签里面配置验证规则,如表达式验证
(4)在message里面定义错误信息
(5)在页面上使用s:actionerror标签显示错误信息
9、字段验证和非字段验证区别:
(1)字段验证优先于非字段验证,而且可以为一个字段配置多个验证规则
(2)按照规则来验证的一般都用非字段验证
(3)多数验证都支持字段验证和非字段验证,但如表达式验证的验证方式,只能用非字段验证
10、自定义验证器步骤:
(1)自定义验证器类
验证逻辑:TestNumber.java 判断输入的字符串中有没有 “666”
验证器类:NumberValidator.java 自定义验证器
(1)自定义验证器需要实现Validator
(2)验证器类要继承ValidatorSupport或者FieldValidatorSupport
(3)ValidatorSupport:需要实现一般验证器时候用
(4)FieldValidatorSupport:需要实现一个字段验证器
(2)配置自定义验证器
自定义验证器加载的资源文件:validators.xml
(1)默认情况,struts2会在类路径根目录加载validators.xml,在这个xml中加载验证器
(2)类路径下没指定验证器,从默认验证器配置(com.opensymphony.xwork2.validator.validators/default.xml)中加载
(3)使用:跟默认验证器一样
(1)到actionClassName-validation.xml或者actionClass-actionName-validation.xml配置自定义验证器
(2)页面上使用自定义验证器的元素,并用s:fielderror写上对应的错误输出
11、声明式验证步骤
(1)配置struts.xml
(2)编写页面调用验证用的action类
(3)编写action类
(4)在action类所在包下新建配置文件actionClassName-validation.xml或者actionClassName-actionName-validation.xml并在里面写上所需要的验证规则
(5)配置国际化资源文件
(6)根据需求(短路验证不通过的时候不执行后续验证器)重写com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor
12、编程式验证步骤:
(1)编写调用的页面
(2)编写验证需要验证字段的验证逻辑
(3)编写使用验证逻辑的验证类
(4)在src下配置validators.xml
(5)在actionClassName-validation.xml或者actionClassName-actionName-validation.xml中配置,配置对应字段的验证规则时,把field-validator标签的type设为validators.xml中配置的验证器名
13、index.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>index</title>
</head>
<body>
<!--
验证方式:
1、声明式验证
(1)对哪个action/model的哪个自断进行验证
(2)使用什么验证规则
(3)验证失败,跳转到哪里,显示什么错误信息
2、编程式验证
配置步骤:
1、确认需要验证的字段名
2、编写配置文件
I、当一个action类的多个actino使用相同验证规则,在当前action所在包下新建 actionClassName-validation.xml
II、当一个action类的多个action使用不同验证规则,在当前action所在包下新建actionClassName-actionName-validation.xml
(1)把xml的头设置为xwork validation的头
(2)用validators标签包着准备编写的规则
(3)参照以下地址的验证字段说明,编写验证规则:https://struts.apache.org/core-developers/validation.html
(4)对错误消息进行国际化,即field标签中的message内容国际化
3、国际化错误信息
(1)在struts.xml配置国际化资源文件的constant
(2)在action-validation.xml中,把验证的message标签写成 用key关联国际化资源文件的字段名的形式,字段值可以包含${验证规则值}的内容 如:整型验证中国际化文件 ${fieldName} ${min} ${max} 分别动态的读取到配置文件中的字段名、最小值、最大值,使得错误信息可以适配多个不同字段的相同验证规则的响应消息
(3)如果在国际化资源文件中适用多个字段的验证规则使用的提示信息里面的\$\{\}中再配置对应字段内容时,可以使用\$ \{get Text(fieldName)\}
如:error.int里面的第一个\$\{\}需要按照调用error.int的字段来分别读入age或者age2内容时
配置内容:
error.int=\$\{get Text(fieldName)\} needs to be between 1 and 10
age=Age
age2=Age2
读取结果:
I、age字段调用error.int显示提示信息
结果为:Age needs to be between 1 and 10
II、age2字段调用error.int显示提示信息
结果为:Age2 needs to be between 1 and 10
4、确定验证失败时的响应页面
(1)配置strut.xml中验证失败的result,result的name必须为input 如:<result name="result">/xxx.jsp</result>
(2)页面显示错误信息, 如form使用非simole主题,页面会自动显示,
如form使用非simple主题,则需要用 s:fielderror fieldName="字段名"标签或者${fieldErrors.字段名[0]}显示错误
用s:fielderror标签显示错误时,如果有多个错误信息,则会一次性全部都显示到页面
注意事项:
1、如果一个action类的多个action使用不同验证规则,这些需要对应不同action新建对应的actionClassName-actionName-validation.xml
2、不带action名的配置文件 actionClassName-validation.xml的验证规则不管什么情况都会运行的,所以不是公用的验证规则不要写到actionClassName-validation.xml里面
声明式验证运行原理:
1、struts2默认拦截器栈中提供了一个validation拦截器
2、每个验证规则都会对应一个验证器,具体可以看xwork-core-x.x.xx.x.jar的如下文件:
com.opensymphony.xwork2.validator.validators包里面的default.xml
短路验证:
1、在actionClassName-validation.xml或者ClassName-actionName-validation.xml中的validator标签或者field-validator标签里面配置,默认false
2、关键字:short-circuit
3、一个字段使用多个验证器时,默认按顺序执行该字段已配置的所有验证,如果希望前一个验证不通过时候,后面的验证都不执行,就需要使用短路验证了
类型转换失败,直接获得错误信息,不再执行后续验证拦截器
1、如果action在param拦截器中的ConversionErrorInterceptor拦截器里面就已经发现类型转换错误,希望直接输出错误信息而不继续去执行验证拦截器时,就应该按照下面注意事项2的步骤重写ConversionErrorInterceptor类,使得程序在ConversionErrorInterceptor拦截器得到运行返回结果后停止运行并返回结果到值栈中的错误信息参数中
注意事项2:
1、类型转换出错时,重新定义错误显示,统一错误信息
(1)找到xwork-core-x.x.xx.x.jar里面的com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor类
(2)在src下新建com.opensymphony.xwork2.interceptor包,并且重写ConversionErrorInterceptor
(3)验证拦截器是在ConversionErrorInterceptor拦截器之后运行的,就是说struts2会先检查类型转换或数据类型,然后就会去运行验证拦截器,如果出现数据类型出错,而且验证拦截器也验证数据类型的情况,页面就会分别从ConversionErrorInterceptor拦截器和验证拦截器获得各自的数据类型出错的错误信息
(4)为了避免ConversionErrorInterceptor拦截器和验证拦截器的错误信息不统一,和无意义地多运行一次数据类型验证拦截器,所以要重写ConversionErrorInterceptor中对当前调用action判断出错的语句(见ConversionErrorInterceptor。java的139-147行),可以达到,如果类型转换出问题时,不用通过运行验证拦截器多进行一次数据类新验证,直接根据ConversionErrorInterceptor拦截器的结果就输出类型转换的错误就可以了
非字段验证:
1、不是特定某个字段的验证
2、需要在validators里面新建一个type为expression的validator标签
3、在param name为expression的标签里面配置验证规则,如表达式验证
4、在message里面定义错误信息
5、在页面上使用s:actionerror标签显示错误信息
字段验证和非字段验证区别:
1、字段验证优先于非字段验证,而且可以为一个字段配置多个验证规则
2、按照规则来验证的一般都用非字段验证
3、多数验证都支持字段验证和非字段验证,但如表达式验证的验证方式,只能用非字段验证
自定义验证器步骤:
1、自定义验证器类
验证逻辑:TestNumber.java 判断输入的字符串中有没有 “666”
验证器类:NumberValidator.java 自定义验证器
(1)自定义验证器需要实现Validator
(2)验证器类要继承ValidatorSupport 或者 FieldValidatorSupport
(3)ValidatorSupport : 需要实现一般验证器时候用
FieldValidatorSupport : 需要实现一个字段验证器
2、配置自定义验证器
自定义验证器加载的资源文件:validators.xml
(1)默认情况,struts2会在类路径根目录加载validators.xml,在这个xml中加载验证器
validators.xml的定义方式跟默认验证器配置(com.opensymphony.xwork2.validator.validators/default.xml)一样
(2)类路径下没指定验证器,从默认验证器配置(com.opensymphony.xwork2.validator.validators/default.xml)中加载
3、使用:跟默认验证器一样
(1)到actionClassName-validation.xml或者actionClass-actionName-validation.xml配置自定义验证器
(2)页面上使用自定义验证器的元素,并用s:fielderror写上对应的错误输出
-->
<!-- 使用TestValidationAction-testValidation-validation.xml的验证规则进行验证 -->
<a href="testValidation?request_locale=en_US">English</a><br>
<a href="testValidation?request_locale=zh_CN">中文</a><br>
<s:debug></s:debug>
<s:form action="testValidation" theme="simple">
s:fielderror : <s:fielderror fieldName="age"></s:fielderror><br>
fieldErrors : ${fieldErrors.age[0] }<br>
Age:<s:textfield name="age" label="Age"></s:textfield><br>
password:<s:textfield name="password" label="password"></s:textfield><br>
password Confirm:<s:textfield name="passwordConfirm" label="passwordConfirm"></s:textfield><br>
<s:actionerror></s:actionerror><br>
<br>测试自定义验证器用<br>
number:<s:textfield name="number" label="number"></s:textfield><br>
<s:fielderror fieldName="number"></s:fielderror><br>
<s:submit></s:submit>
</s:form>
</body>
</html>
14、TestValidationAction.java验证字段的model类
package com.demo.sshtest;
import com.opensymphony.xwork2.ActionSupport;
public class TestValidationAction extends ActionSupport{
private static final long serialVersionUID = 1L;
public int age;
public String password;
public String passwordConfirm;
public String number;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String execute() throws Exception {
System.out.println("age:"+getAge());
System.out.println("password:"+getPassword());
System.out.println("passwordConfirm:"+getPasswordConfirm());
System.out.println("number:"+getNumber());
return SUCCESS;
}
}
15、TestValidationAction-testValidation-validation.xml验证配置文件
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- 注意文件头,要是xwork的validaot头,不然验证器就会没反应 -->
<validators>
<!-- 一个field中 可以配置多个类型的验证器 -->
<field name="age">
<!-- 转换类型验证器 -->
<!--短路验证
1、关键字:short-circuit
2、使用短路验证后,当前验证不通过就不执行后面验证 如:conversion的验证不通过时,系统不会执行后面对int的验证
-->
<field-validator type="conversion" short-circuit="true">
<message key="error.int.coversion"></message>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="error.int"></message>
</field-validator>
</field>
<!-- 非字段验证 -->
<validator type="expression" short-circuit="true">
<param name="expression"><![CDATA[password==passwordConfirm]]></param>
<message key="pswdEqualsValidation"></message>
</validator>
<!-- 配置自定义验证器 -->
<field name="number">
<field-validator type="myValidator">
<message>myValidator work</message>
</field-validator>
</field>
</validators>
16、i18n.properties/i18n_zh_CN.properties/i18n_en_US.properties国际化资源文件
error.int=${getText(fieldName)} needs to be between ${min} and ${max}
error.int.coversion=Conversion Error Occurred
pswdEqualsValidation=password no equals to passwordConfirm
age=Age
demo中有个index2.jsp文件,是用来测试相同字段使用不同验证规则用的,这种情况就需要使用actionClassName-actionName-validation.xml这种命名方式,根据actionName来告诉struts2究竟调用的是哪个验证规则,result.jsp就是公用的结果页面,这里就不写了,字段式验证就写完了
这里开始的文件是自定义验证器
17、TestNumber.java验证age的逻辑
package com.demo.sshtest;
public class TestNumber {
public static boolean exist666(String number) {
boolean result = false;
if(number.indexOf("666")!=-1) {
result = true;
}
return result;
}
public static void main(String[] args) {
System.out.println("-----"+exist666("4234266634233"));
System.out.println("-----"+exist666("4232623513666"));
System.out.println("-----"+exist666("6664232623513"));
}
}
18、NumberValidator.java验证器类
package com.demo.sshtest;
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;
public class NumberValidator extends FieldValidatorSupport{
@Override
public void validate(Object arg0) throws ValidationException {
//1、获取字段名和值
String fieldName = this.getFieldName();
Object value = this.getFieldValue(fieldName, arg0);
//2、验证
TestNumber testNumber = new TestNumber();
boolean rs = testNumber.exist666((String)value);
//3、验证失败处理
if(!rs) {
addFieldError(fieldName, arg0);
}
}
}
(1)要继承FieldValidatorSupport类(2)验证失败时,通过addFieldError()方法,把错误压进FieldErrors里面
19、validators.xml在src下定义这个验证器配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator Definition 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
<validators>
<validator name="myValidator" class="com.demo.sshtest.NumberValidator"/>
</validators>
20、在准备调用验证器的actionClassName-validation.xml或者actionClassName-actionName-validation.xml中配置需要配置字段的验证器,并且field-validator的type为validators.xml中validator名
21、注意事项:
(1)在actionClassName-validation.xml或者actionClassName-actionName-validation.xml中,字段验证的时候,如果想前一个验证器报错的时候,下一个不执行,就需要在field-validator标签中,加上short-circuit=”true”
22、这个笔记内容比较多,写起来比较乱,所以最好下载demo运行一次看看
23、运行结果
(1)字段验证第一个验证就不通过
(2)字段验证第二个验证就不通过
(3)字段验证通过,自定义验证器不通过
24、项目目录
25、demo中配置TestValidationAction-testValidation-validation.xml的时候,有部分验证器规则忘记配短路验证了,所以以这篇文章中的TestValidationAction-testValidation-validation.xml写法为准
26、demo
https://download.csdn.net/download/qq_22778717/10320991