Struts2中提供了数据校验验证数据例如验证邮件、数字等。验证方式有3种:
一是通过validate()方法,
二是通过Xml,
三是使用注解方式。
一、初始化
首先定义一个User类
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 |
package com.cyw.test; import java.util.Date; public class User { private String name; private int age; private String email; public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } public String getEmail() { return email; } public void setEmail(String email) { this .email = email; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this .birthDay = birthDay; } private Date birthDay; } |
二、validate()方法验证
可以在继承了ActionSupport的Action中重写validate()来进行验证。validate()方法会在execute()方法执行前执行,仅当数据校验正确,才执行execute()方法, 如错误则将错误添加到fieldErrors域中,如果定义的Action中存在多个逻辑处理方法,且不同的处理逻辑需要不同的校验规则,这种情况下validate()会对所有处理逻辑使用相同的校验规则,为了实现不同的校验逻辑,需要通过validateX()方法,其中X表示处理逻辑的方法名,如果有错误系统会返回result name="input"的页面,所以需要在action中定义一个input的result。我昨天就困在这个地方好久。问了我大学同学才解决,为了这个validate()验证昨晚一点多都没睡,虽然SSH框架现在不流行,特别是前几天struts2报了一个远程bug,不过想着既然学java了,就系统的学一遍吧。
1.validate()方法
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
package com.cyw.test; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; public class ValidatorAction extends ActionSupport { private User user; private ListuserList= new ArrayList(); public List getUserList() { return userList; } public void setUserList(List userList) { this .userList = userList; } @Override public String execute() throws Exception { if (user== null || this .hasFieldErrors()) { return "regist" ; } else { return "success" ; } } public String addUser() { userList.add(user); return "success" ; } private static final long serialVersionUID = 1L; public User getUser() { return user; } public void setUser(User user) { this .user = user; } @Override public void validate() { if (user!= null ) { if (!dataPass( user.getName(), "^[A-Za-z][A-Za-z1-9_-]+$" )) { addFieldError( "user.name" , "用户名(字母开头 + 数字/字母/下划线)" ); } if (!dataPass(String.format( "%d" , user.getAge()) , "(?:[1-9][0-9]?|1[01][0-9]|120)" )) { addFieldError( "user.name" , "年龄0-120之间" ); } Date startDate=strToDate( "1900-01-01" ); Date endDate=strToDate( "2017-01-01" ); if (user.getBirthDay().before(startDate) || user.getBirthDay().after(endDate) ) { addFieldError( "birthDay" , "出生日期在1900-01-01至2017-01-01之间。" ); } if (!dataPass(user.getEmail(), "^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}$" )) { addFieldError( "email" , "邮箱格式不符合" ); } } } private Date strToDate(String strDate) { SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd" ); ParsePosition pos = new ParsePosition( 0 ); Date strtodate = formatter.parse(strDate, pos); return strtodate; } private boolean dataPass(String str,String regEx) { Pattern pattern=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE); Matcher matcher =pattern.matcher(str); return matcher.matches(); } } |
struts.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
xml version = "1.0" encoding = "UTF-8" ?>
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> < struts > < package name = "default" namespace = "" extends = "struts-default" > < action name = "regist" class = "com.cyw.test.ValidatorAction" > < result name = "regist" >/register.jspresult > < result name = "success" >/success.jspresult > < result name = "input" >/register.jspresult > action >
package >
struts >
|
2.validateX()方法
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
package com.cyw.test; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; public class ValidatorAction extends ActionSupport { private User user; private ListuserList= new ArrayList(); public List getUserList() { return userList; } public void setUserList(List userList) { this .userList = userList; } public String addUser() { if (user== null ) { return "regist" ; } userList.add(user); return "success" ; } private static final long serialVersionUID = 1L; public User getUser() { return user; } public void setUser(User user) { this .user = user; } public void validateAddUser() { if (user!= null ) { if (!dataPass( user.getName(), "^[A-Za-z][A-Za-z1-9_-]+$" )) { addFieldError( "user.name" , "用户名(字母开头 + 数字/字母/下划线)" ); } if (!dataPass(String.format( "%d" , user.getAge()) , "(?:[1-9][0-9]?|1[01][0-9]|120)" )) { addFieldError( "user.name" , "年龄0-120之间" ); } Date startDate=strToDate( "1900-01-01" ); Date endDate=strToDate( "2017-01-01" ); if (user.getBirthDay().before(startDate) || user.getBirthDay().after(endDate) ) { addFieldError( "birthDay" , "出生日期在1900-01-01至2017-01-01之间。" ); } if (!dataPass(user.getEmail(), "^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}$" )) { addFieldError( "email" , "邮箱格式不符合" ); } } } private Date strToDate(String strDate) { SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd" ); ParsePosition pos = new ParsePosition( 0 ); Date strtodate = formatter.parse(strDate, pos); return strtodate; } private boolean dataPass(String str,String regEx) { Pattern pattern=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE); Matcher matcher =pattern.matcher(str); return matcher.matches(); } } |
struts.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
xml version = "1.0" encoding = "UTF-8" ?>
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> < struts > < package name = "default" namespace = "" extends = "struts-default" > < action name = "regist" class = "com.cyw.test.ValidatorAction" method = "addUser" > < result name = "regist" >/register.jspresult > < result name = "success" >/success.jspresult > < result name = "input" >/register.jspresult > action >
package >
struts >
|
JSP:
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 |
<%@ page language= "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8" %> <%@ taglib uri= "/struts-tags" prefix= "struts" %> "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
"Content-Type" content= "text/html; charset=UTF-8" >
注册页面
"name" >
"regist" method= "post" >
"user.name" label= "用户名" >
"user.age" label= "年龄" >
"user.birthDay" label= "出生日期" >
"user.email" label= "邮箱" >
"注册" >
|
二、XML验证
使用validate方法校验时,如果Web应用中存在大量Action就需要多次重写validate方法,因此可以使用XWork的validator框架来对Struts2进行数据校验,减少代码量。在action包下创建验证文件XXX-validation.xml,注:当一个Action中有多个业务处理方法是,命名规则为:actionName-methodName-validation.xml,其中actionName为Action类名,methodName为Action中某个业务处理方法的方法名,并且文件的搜索顺序与方式一种validate()和validateX()一样。
这里先注释掉Action的验证方法,然后新增一个xml验证文件,最后要在form中增加validate="true"
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 |
xml version = "1.0" encoding = "UTF-8" ?>
"-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> < validators > < field name = "user。name" > < field-validator type = "regex" > < param name = "expression" >
param >
< message >用户名必须在4到20 之间,且必须是字母或者数字message > field-validator >
field >
< field name = "user.email" > < field-validator type = "email" > < message >你的电子邮件地址必须是一个有效的电邮地址message > field-validator >
field >
< field name = "user.age" > < field-validator type = "int" > < param name = "min" >1param > < param name = "max" >120param > < message >年纪必须在1到120之间message > field-validator >
field >
< field name = "user.birthDay" > < field-validator type = "date" short-circuit = "true" > < param name = "min" >1900-01-01param > < param name = "max" >2050-02-21param > < message >生日在${min}到${max}之间message > field-validator >
field >
validators >
|
这里遗留了两个问题,一是错误信息不是一次全部显示出来,如上面两个图先显示两个错误提示,然后将显示的修改正确之后又显示其他的,这为什么不是全部显示出来呢?二是在Xml中使用正则表达式验证怎么不起作用,这个也是个遗留的问题,先把这两个问题放在这里,等以后再问下其他人,如果哪位读者知道原因也希望留言告诉博主,先谢过了。
三、注解
1.Validations Annotation的使用
Validations中定义了一些验证器的数组,用于存放验证规则,定义如下:
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 |
public @interface Validations { //自定义校验器数组 public CustomValidator[] customValidators() default {}; //字段转换错误校验器数组 public ConversionErrorFieldValidator[] conversionErrorFields() default {}; //日期范围校验器 public DateRangeFieldValidator[] dateRangeFields() default {}; //Email校验器 public EmailValidator[] emails() default {}; //字段表达式校验器 public FieldExpressionValidator[] fieldExpressions() default {}; //整数范围校验器 public IntRangeFieldValidator[] intRangeFields() default {}; //必填字段校验器 public RequiredFieldValidator[] requiredFields() default {}; //必填字符串校验器 public RequiredStringValidator[] requiredStrings() default {}; //字符串长度校验器 public StringLengthFieldValidator[] stringLengthFields() default {}; //URL校验器 public UrlValidator[] urls() default {}; //带条件的Vistor校验器 public ConditionalVisitorFieldValidator[] conditionalVisitorFields() default {}; //Vistor校验器 public VisitorFieldValidator[] visitorFields() default {}; //正则表达式校验器 public RegexFieldValidator[] regexFields() default {}; //表达式校验器 public ExpressionValidator[] expressions() default {}; } |
RequiredStringValidator —— 必填字符串校验器
校验要求:指定字段不能为null且字符串长度大于0
参数:
- fieldName:校验字段名
- trim:校验时取出字符串两边的空格,默认为true
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
RequiredFieldValidator —— 必填校验器
校验要求:指定字段不能为null
参数:
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
IntRangeFieldValidator —— 整数范围校验器
校验要求:int、long、short字段的整数值在指定的范围内
参数:
- min:指定最小值,可选,没有则不检查最小值
- max:指定最大值,可选,没有则不检查最大值
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
DateRangeFieldValidator —— 日期范围校验器
校验要求:日期在指定的范围内
参数:
- min:指定最小值,可选,没有则不检查最小值
- max:指定最大值,可选,没有则不检查最大值
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
EmailValidator —— Email地址校验器
校验要求:指定的字段为Email地址
参数:
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
ExpressionValidator —— 表达式校验器
校验要求:指定的ONGL表达式返回true。
参数:
- expression:ONGL表达式
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
UrlValidator —— URL校验器
校验要求:校验指定的字段值是否为合法的URL
参数:
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
StringLengthFieldValidator —— 字符串长度校验器
校验要求:字符串长度在指定的范围内
参数:
- minLength:指定最小长度,可选,没有则不检查最小长度
- maxLength:指定最大长度,可选,没有则不检查最大长度
- trim:校验时取出字符串两边的空格,默认为true
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
ConversionErrorFieldValidator —— 转换错误校验器
校验要求:校验指定字段是否发生类型转换错误
参数:
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
VisitorFieldValidator —— Vistor校验器
说明:普通校验器只能校验基本数据类型和字符串类型,该校验器可以校验对象里面的属性。
参数:
- context:用于校验的context
- appendPrefix: 校验发生错误时是否在错误信息中添加前最消息
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
RegexFieldValidator —— 正则表达式校验器
校验要求:指定字段匹配指定的正则表达式
参数:
- expression:正则表达式
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
-
ConditionalVisitorFieldValidator —— 带条件的Vistor校验器
验证要求:在条件不满足时,和Vistor校验器功能一样,条件满足则不执行Vistor校验
参数:
- fieldName:校验字段名
- message:校验失败时的消息
- key:校验失败时返回i18n中指定名称的消息
CustomValidator —— 自定义校验器
校验器:自定义校验器
举例:
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 |
package com.cyw.test; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.validator.annotations.Validations; import com.opensymphony.xwork2.validator.annotations.*; public class ValidatorAction extends ActionSupport { private User user; private ListuserList= new ArrayList(); public List getUserList() { return userList; } public void setUserList(List userList) { this .userList = userList; } @Validations ( emails={ @EmailValidator (fieldName= "user.email" ,message= "邮件字段的格式不对" )}, conversionErrorFields={ @ConversionErrorFieldValidator (fieldName= "user.age" ,message= "年龄输入的值转换错误" )}, intRangeFields={ @IntRangeFieldValidator (fieldName= "user.age" ,min= "0" ,max= "120" ,message= "年龄范围为0到120" )}, dateRangeFields={ @DateRangeFieldValidator (fieldName= "user.birthDay" ,min= "1900-01-01" ,max= "2017-03-30" ,message= "日期输入不正确" )}, regexFields={ @RegexFieldValidator (regexExpression= "^[A-Za-z][A-Za-z1-9_-]+$" ,fieldName= "user.name" ,message= "用户名(字母开头 + 数字/字母/下划线)" )} ) public String addUser() { if (user== null ) { return "regist" ; } userList.add(user); return "success" ; } private static final long serialVersionUID = 1L; public User getUser() { return user; } public void setUser(User user) { this .user = user; } } |
结论:
1.Action类中使用Validations Annotation定义验证。
2.Action中,可以在方法上、类上定义验证Annotations,所有的验证器都将同时作用在映射为Action的方法上。
3.Action中有多个方法被映射为Action时,类上和方法上所有定义的验证Annotations都将作用在每个映射为Action的方法上。
4.Action中校验失败时,返回input逻辑视图
5.可以使用@SkipValidation跳过所有的验证检查,包括自身方法定义的校验器。
6.可以在Action映射中使用如下代码跳过校验检查
1 2 3 |
< interceptor-ref name = "validation" > < param name = "validateAnnotatedMethodOnly" >trueparam > interceptor-ref >
|
遗留问题修改:
上面遗留了一个问题,在xml中来做验证时正则表达式不起作用,保存之后突然想到在注解中用下面的代码来表示的
regexFields={@RegexFieldValidator(regexExpression="^[A-Za-z][A-Za-z1-9_-]+$",fieldName="user.name",message="用户名(字母开头 + 数字/字母/下划线)")}
看着参数名和xml中配置的不一样,会不会是参数名错误呢?因为我在网上查的有的用regex或expression,不过都说在提问说不起作用,我怀疑是不是参数名有问题,报着试一试的态度用regexExpression试一试,没想到还成功了。应该将上面用xml验证name的地方改成这样子。
1 2 3 4 5 6 |
< field name = "user.name" > < field-validator type = "regex" > < param name = "regexExpression" >
param >
< message >用户名(字母开头 + 数字/字母/下划线)message > field-validator >
field >
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。