Struts2之Validator
Struts2中提供了数据校验验证数据例如验证邮件、数字等。验证方式有3种:一是通过validate()方法,二是通过Xml,三是使用注解方式。
一、初始化
首先定义一个User类
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()方法
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 List<User>userList=new ArrayList<User>();
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> 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();
} }
<?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>
<package name="default" namespace="" extends="struts-default">
<action name="regist" class="com.cyw.test.ValidatorAction">
<result name="regist">/register.jsp</result>
<result name="success">/success.jsp</result>
<result name="input">/register.jsp</result>
</action>
</package>
</struts>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="struts" %>
<!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>
<struts:fielderror key="name"></struts:fielderror>
<struts:form action="regist" method="post">
<struts:textfield name="user.name" label="用户名"></struts:textfield>
<br/>
<struts:textfield name="user.age" label="年龄"></struts:textfield>
<br/>
<struts:textfield name="user.birthDay" label="出生日期"></struts:textfield> <br/>
<struts:textfield name="user.email" label="邮箱"></struts:textfield>
<br/>
<struts:submit value="注册"></struts:submit>
</struts:form>
</body>
</html>
2.validateX()方法
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 List<User>userList=new ArrayList<User>();
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> 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();
} }
<?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>
<package name="default" namespace="" extends="struts-default">
<action name="regist" class="com.cyw.test.ValidatorAction" method="addUser">
<result name="regist">/register.jsp</result>
<result name="success">/success.jsp</result>
<result name="input">/register.jsp</result>
</action>
</package>
</struts>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="struts" %>
<!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>
<struts:fielderror key="name"></struts:fielderror>
<struts:form action="regist" method="post">
<struts:textfield name="user.name" label="用户名"></struts:textfield>
<br/>
<struts:textfield name="user.age" label="年龄"></struts:textfield>
<br/>
<struts:textfield name="user.birthDay" label="出生日期"></struts:textfield> <br/>
<struts:textfield name="user.email" label="邮箱"></struts:textfield>
<br/>
<struts:submit value="注册"></struts:submit>
</struts:form>
</body>
</html>
二、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"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//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"><![CDATA[(\w{4,20})]]></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">1</param>
<param name="max">120</param>
<message>年纪必须在1到120之间</message>
</field-validator>
</field>
<field name="user.birthDay" >
<field-validator type="date" short-circuit="true">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>生日在${min}到${max}之间</message>
</field-validator>
</field>
</validators>
这里遗留了两个问题,一是错误信息不是一次全部显示出来,如上面两个图先显示两个错误提示,然后将显示的修改正确之后又显示其他的,这为什么不是全部显示出来呢?二是在Xml中使用正则表达式验证怎么不起作用,这个也是个遗留的问题,先把这两个问题放在这里,等以后再问下其他人,如果哪位读者知道原因也希望留言告诉博主,先谢过了。
三、注解
1.Validations Annotation的使用
Validations中定义了一些验证器的数组,用于存放验证规则,定义如下
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 —— 自定义校验器
校验器:自定义校验器
举例:
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 List<User>userList=new ArrayList<User>();
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> 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映射中使用如下代码跳过校验检查
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
</interceptor-ref>
遗留问题修改:
上面遗留了一个问题,在xml中来做验证时正则表达式不起作用,保存之后突然想到在注解中用下面的代码来表示的
regexFields={@RegexFieldValidator(regexExpression="^[A-Za-z][A-Za-z1-9_-]+$",fieldName="user.name",message="用户名(字母开头 + 数字/字母/下划线)")}
看着参数名和xml中配置的不一样,会不会是参数名错误呢?因为我在网上查的有的用regex或expression,不过都说在提问说不起作用,我怀疑是不是参数名有问题,甚至在一些教程网http://www.yiibai.com/struts_2/xml_based_validators.html上用的也是expression,报着试一试的态度用regexExpression试一试,没想到还成功了。应该将上面用xml验证name的地方改成这样子。
<field name="user.name">
<field-validator type="regex">
<param name="regexExpression"><![CDATA[(\^[A-Za-z][A-Za-z1-9_-]+$)]]></param>
<message>用户名(字母开头 + 数字/字母/下划线)</message>
</field-validator>
</field>
Struts2之Validator的更多相关文章
- 关于Struts2的Validator的配置找不到DTD
看教材的时候写的DTD是 <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN&q ...
- Struts2的validator和WEB-INF下页面交互以及路径问题
当我使用短路校验器时(客户端),在页面下方老是出来 FreeMarker template error!然后我就把我的页面都放在了WEB-INF中,结果很多路径都不对了,因为客户端是没有直接访问Str ...
- struts2学习笔记--使用Validator校验数据
我们在进行一些操作是需要对用户的输入数据进行验证,比如网站的注册,需要对各个数据项进行数据校验,Struts2提供了一些默认的校验器,比如数字的检测,邮箱的检测,字符串长度的检测等等. 常用的Vali ...
- 菜鸟学Struts2——零配置(Convention )
又是周末,继续Struts2的学习,之前学习了,Struts的原理,Actions以及Results,今天对对Struts的Convention Plugin进行学习,如下图: Struts Conv ...
- 9、 Struts2验证(声明式验证、自定义验证器)
1. 什么是Struts2 验证器 一个健壮的 web 应用程序必须确保用户输入是合法.有效的. Struts2 的输入验证 基于 XWork Validation Framework 的声明式验证: ...
- Struts2数据校验
Struts2数据校验 1.常见数据校验方法 表单数据的校验方式: 表单中的数据必须被效验以后才能够被使用,常用的效验方式分为两种: 前台校验:也称之为客户端效验,主要是通过JS编程的方式进行表单数据 ...
- Struts2入门(四)——数据输入验证
一.前言 1.1.什么是输入验证?为什么需要输入验证? 在上一篇文章中,我们学习了数据类型转换,我们提到了表示层数据处理的两个方法,也提到了用户输入数据需要进行类型转换才能得到我们想要的数据,那么,我 ...
- struts2笔记(3)
关于回显: 如果是int型,默认就会回显为0,如果不想让回显,则Integer就好 //**************************************声明式验证************* ...
- Struts2
为什么要用Struts2? 这里列举一些Servlet的缺点: 1.每写一个servlet在web.xml中都要做相应的配置.如果有多很servlet,会导致web.xml内容过于繁多. 2.这样的结 ...
随机推荐
- ConOS安装mysql5.7 及简单配置
安装 保证你的用户有权限 安装 没有 切换 root su root (su的意思:swich user) # rpm -ivh http://dev.mysql.com/get/mysql57- ...
- php微信网页授权获取用户信息
配置回调域名: 1. 引导用户进入授权页面同意授权,获取code 2. 通过code换取网页授权access_token(与基础支持中的access_token不同) 3. 如果需要,开发者可以刷新网 ...
- C++待解
//[要求]按以下描述和要求建立一个含有对象成员的类TeleBook,用类Record定义的数组是TeleBook的数据成员. // 写出所有定义成员函数的代码.执行主函数对其测试. Record私有 ...
- BZOJ ac100题存档
不知不觉AC100题了,放眼望去好像都是水题.在这里就做一个存档吧(特别感谢各位大神尤其是云神http://hi.baidu.com/greencloud和丽洁姐http://wjmzbmr.com/ ...
- C# 控制台倒计时
年前经常聊天的大佬群里有人写了窗体的倒计时来计算下班时间和放假时间:) 简直就是在嘲讽我这种没有工作的人,哈哈哈 窗体的倒计时相当的没有技术含量,主要是不够炫酷,不能够体现我们程序员的身份. 那什么才 ...
- ios用户体验
如果转载此文,请注明出处:http://blog.csdn.net/paulery2012/article/details/25157347,谢谢! 前言: 本文是在阅读<ios用户体验> ...
- 使用StyleCop.Analyzers进行代码审查
为什么要进行代码审核? 提早发现代码中的BUG,避免将BUG带到生产环境 极大的提高软件质量,以及可维护性 统一代码规范.提高可读性,减少新加入成员的熟悉时间 加速个人和团队的成长,知识和经验的积累 ...
- 用react分页显示数据
去年年底,尝试着用react写个组件化的页面! demo地址 里面有一个list页面弄了一下数据的分页展示 展示一下主要三个组件:父组件listBox.列表组件List.按钮组件PageButton ...
- 整理 - .Net系统预定义的委托们
大部分情况下,我们可以使用系统预定义的委托类型,而不需要自己再来手动定义. 以下委托都位于System命名空间下. 传入参数.返回值的类型,大都被声明为泛型. 1.Action系列 有0-16个参数, ...
- 规范 : jobbox 中英文
中英文是为了candidate 可以看到不同的post job 语言. e.g. 如果是contact person 的“designation” ,这个不会显示在post job 里,目的只是给em ...