Struts2之Validator验证框架的详细介绍

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 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();

 }

}

struts.xml:

1

2

3

4

5

6

7

8

9

10

11

12

13

<?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>

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 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();

 }

 

}

struts.xml:

1

2

3

4

5

6

7

8

9

10

11

12

13

<?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>

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" %>

<!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"

 

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"?>

 <!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中定义了一些验证器的数组,用于存放验证规则,定义如下:

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

参数:

  1. fieldName:校验字段名
  2. trim:校验时取出字符串两边的空格,默认为true 
  3. message:校验失败时的消息
  4. key:校验失败时返回i18n中指定名称的消息

RequiredFieldValidator —— 必填校验器

校验要求:指定字段不能为null

参数:

  1. fieldName:校验字段名
  2. message:校验失败时的消息
  3. key:校验失败时返回i18n中指定名称的消息

IntRangeFieldValidator —— 整数范围校验器

校验要求:int、long、short字段的整数值在指定的范围内

参数:

  1. min:指定最小值,可选,没有则不检查最小值
  2. max:指定最大值,可选,没有则不检查最大值
  3. fieldName:校验字段名
  4. message:校验失败时的消息
  5. key:校验失败时返回i18n中指定名称的消息

DateRangeFieldValidator —— 日期范围校验器

校验要求:日期在指定的范围内   

参数:

  1. min:指定最小值,可选,没有则不检查最小值
  2. max:指定最大值,可选,没有则不检查最大值 
  3. fieldName:校验字段名
  4. message:校验失败时的消息
  5. key:校验失败时返回i18n中指定名称的消息

EmailValidator —— Email地址校验器

校验要求:指定的字段为Email地址

参数:

  1.  fieldName:校验字段名
  2. message:校验失败时的消息
  3. key:校验失败时返回i18n中指定名称的消息

ExpressionValidator —— 表达式校验器

校验要求:指定的ONGL表达式返回true。

参数:

  1. expression:ONGL表达式   
  2. message:校验失败时的消息
  3. key:校验失败时返回i18n中指定名称的消息

UrlValidator —— URL校验器

校验要求:校验指定的字段值是否为合法的URL

参数:

  1.  fieldName:校验字段名
  2. message:校验失败时的消息
  3. key:校验失败时返回i18n中指定名称的消息

StringLengthFieldValidator —— 字符串长度校验器

校验要求:字符串长度在指定的范围内

参数:

  1. minLength:指定最小长度,可选,没有则不检查最小长度
  2. maxLength:指定最大长度,可选,没有则不检查最大长度 
  3. trim:校验时取出字符串两边的空格,默认为true 
  4. fieldName:校验字段名
  5. message:校验失败时的消息
  6. key:校验失败时返回i18n中指定名称的消息

ConversionErrorFieldValidator —— 转换错误校验器

校验要求:校验指定字段是否发生类型转换错误

参数:

  1.  fieldName:校验字段名
  2. message:校验失败时的消息
  3. key:校验失败时返回i18n中指定名称的消息

VisitorFieldValidator —— Vistor校验器

说明:普通校验器只能校验基本数据类型和字符串类型,该校验器可以校验对象里面的属性。

参数:

  1. context:用于校验的context
  2. appendPrefix: 校验发生错误时是否在错误信息中添加前最消息
  3. fieldName:校验字段名
  4. message:校验失败时的消息
  5. key:校验失败时返回i18n中指定名称的消息

RegexFieldValidator —— 正则表达式校验器

校验要求:指定字段匹配指定的正则表达式

参数:

  1. expression:正则表达式
  2. fieldName:校验字段名
  3. message:校验失败时的消息
  4. key:校验失败时返回i18n中指定名称的消息
  5.  

ConditionalVisitorFieldValidator —— 带条件的Vistor校验器

验证要求:在条件不满足时,和Vistor校验器功能一样,条件满足则不执行Vistor校验

参数:

  1.  fieldName:校验字段名
  2. message:校验失败时的消息
  3. 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 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映射中使用如下代码跳过校验检查

1

2

3

<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,不过都说在提问说不起作用,我怀疑是不是参数名有问题,报着试一试的态度用regexExpression试一试,没想到还成功了。应该将上面用xml验证name的地方改成这样子。

1

2

3

4

5

6

<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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值