好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring 校验(validator,JSR-303)简单实现方式

Spring 校验(validator,JSR-303)实现

什么是JSR-303规范

JSR 303是Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是hibernate Validator,此实现与Hibernate ORM没有任何关系。JSR 303用于对Java Bean中的字段的值进行验证。

与Spring MVC结合

Spring-mvc.xml配置:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<!--JSR-303-->

< mvc:annotation-driven validator = "validator" />

< bean id = "validator" class = "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >

     < property name = "providerClass" value = "org.hibernate.validator.HibernateValidator" />

     < property name = "validationMessageSource" ref = "messageSource" />

</ bean >

< bean id = "messageSource" class = "org.springframework.context.support.ReloadableResourceBundleMessageSource" >

     < property name = "basename" value = "validatemessage" />

     < property name = "useCodeAsDefaultMessage" value = "false" />

     < property name = "defaultEncoding" value = "UTF-8" />

     < property name = "cacheSeconds" value = "60" />

</ bean >

< bean   id = "webBindingInitializer" class = "org.springframework.web.bind.support.ConfigurableWebBindingInitializer" >

     < property name = "conversionService" >

         < bean class = "org.springframework.format.support.FormattingConversionServiceFactoryBean" ></ bean >

     </ property >

     < property name = "validator" ref = "validator" />

</ bean >

实体类添加验证注解

这里贴出部分代码,知道如何加注解即可:

?

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

import com.lemontree.common.utils.AjaxResult;

import com.lemontree.common.utils.StringUtil;

import com.lemontree.common.utils.email.EmailUtils;

import org.hibernate.validator.constraints.NotEmpty;

import java.util.Date;

public class User {

     /**

      * This field was generated by MyBatis Generator.

      * This field corresponds to the database column user.id

      *

      * @mbg.generated Thu Mar 16 13:27:38 CST 2017

      */

     private Integer id;

     /**

      * This field was generated by MyBatis Generator.

      * This field corresponds to the database column user.user_name

      *

      * @mbg.generated Thu Mar 16 13:27:38 CST 2017

      */

     @NotEmpty (message = "用户名不能为空" )

     private String userName;

     /**

      * This field was generated by MyBatis Generator.

      * This field corresponds to the database column user.password

      *

      * @mbg.generated Thu Mar 16 13:27:38 CST 2017

      */

     @NotEmpty (message = "密码不能为空" )

     private String password;

     }

控制器验证注解添加

将@Validated 注解跟在实体类前面,BindingResult紧跟其后:

?

1

2

3

4

5

6

7

8

9

10

11

12

@RequestMapping (value = "/login.htm" , method = RequestMethod.POST)

public @ResponseBody AjaxResult login( @Validated User user, BindingResult bindingResult,

                                       HttpServletRequest request, HttpServletResponse response) {

     if (bindingResult.hasErrors()){

         List<FieldError> errorses = bindingResult.getFieldErrors();

         if (CollectionUtils.isNotEmpty(errorses)){

             errorses.forEach(item->{

                 System.out.println(item.getDefaultMessage());

             });

         }

     }

   }

Java Hibernate Validator JSR-303验证

JSR-303是JAVA EE 6中的一项子规范,叫做 Bean Validation,Hibernate Validator是Bean Validation 的参考实现。

实际使用就是通过注解来给字段添加约束,然后校验字段是否符合规范,如果不符合就会抛出异常,以此来减少校验数据的代码,并保证拿到的数据都是符合规范的,也可以和Spring框架配合使用

集成

官方文档

https://mvnrepository.com/artifact/org.hibernate/hibernate-validator

https://mvnrepository.com/artifact/javax.validation/validation-api

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

< dependency >

     < groupId >org.hibernate</ groupId >

     < artifactId >hibernate-validator</ artifactId >

     < version >6.0.10.Final</ version >

</ dependency >

< dependency >

     < groupId >org.glassfish</ groupId >

     < artifactId >javax.el</ artifactId >

     < version >3.0.1-b09</ version >

</ dependency >

< dependency >

     < groupId >javax.validation</ groupId >

     < artifactId >validation-api</ artifactId >

     < version >2.0.1.Final</ version >

</ dependency >

使用

校验对象

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public class JsrTest {

     @NotNull (message = "id不能为空!" )

     @Min (value = 1 , message = "Id只能大于等于1" )

     Integer id;

     @NotNull (message = "姓名不能为空!" )

     String name;

     public void validateParams() {

         Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); //获取一个验证器

         Set<ConstraintViolation<JsrTest>> violationSet = validator.validate( this ); //验证数据,获取到错误集合

         Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();

         if (iterator.hasNext()) {

             String errorMessage = iterator.next().getMessage(); //获取到错误信息

             throw new ValidationException(errorMessage);

         }

     }

     public static void main(String args[]) {

         JsrTest req = new JsrTest();

         req.id = 1 ;

         req.validateParams();

     }

}

像上面那样将在属性上添加注解即可声明约束

校验属性

上面是校验整个对象,也可以单独校验某个字段:

?

1

validator.validateProperty(object, "name" );

分组校验

?

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

public class JsrTest {

     @NotNull (message = "id不能为空!" , groups = {ValidationGroup. class })

     @Min (value = 1 , message = "Id只能大于等于1" )

     Integer id;

     @NotNull (message = "姓名不能为空!" , groups = {ValidationGroup. class })

     String name;

     @DecimalMin (value = "1.1" )

     double price;

     int date;

     public static void validateParams(JsrTest jsrTest) {

         Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

         Set<ConstraintViolation<JsrTest>> violationSet = validator.validate(jsrTest, ValidationGroup. class );

         Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();

         if (iterator.hasNext()) {

             String errorMessage = iterator.next().getMessage();

             throw new ValidationException(errorMessage);

         }

     }

     public static void main(String args[]) {

         JsrTest req = new JsrTest();

         validateParams(req);

     }   

     public interface ValidationGroup {

     }

}

分组校验所指定的calss必须是一个接口,可以指定多个

自定义约束

通常情况下,框架提供的注解已经可以满足正常的验证需求,但是我们也可以自定义注解来满足我们的需求

我们这里的例子是所注释的字符串中不能包含指定字符

?

1

2

3

4

5

6

7

8

9

10

@Target (FIELD)      //元注解,定义该注解使用在字段上

@Retention (RUNTIME) //定义注解的生命周期

@Constraint (validatedBy = CustomValidator. class ) //指明该注解的校验器

@Documented          //表示该注解会被添加到JavaDoc中

public @interface CustomConstraints {

     String message() default "默认异常message" ;

     Class<?>[] groups() default {};

     Class<? extends Payload>[] payload() default {}; //这个属性可以用来标注错误的严重等级,但是并不被API自身所使用

     String value() default " " ;

}

?

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

import javax.validation.ConstraintValidator;

import javax.validation.ConstraintValidatorContext;

/**

  * 需要实现ConstraintValidator接口

  * 泛型的第一个参数是自定义的注解,第二个参数注解所注释的字段的类型

  */

public class CustomValidator implements ConstraintValidator<CustomConstraints, String> {

     private String value;

     /**

      * 初始化调用,拿到注解所指定的value

      *

      * @param constraintAnnotation

      */

     @Override

     public void initialize(CustomConstraints constraintAnnotation) {

         value = constraintAnnotation.value();

     }

     /**

      * @param value   注释的字段的值

      * @param context

      * @return true 通过验证,false 未通过验证

      */

     @Override

     public boolean isValid(String value, ConstraintValidatorContext context) {

         if (value != null && value.contains( this .value)) {

             context.disableDefaultConstraintViolation(); //禁用默认的消息

             context.buildConstraintViolationWithTemplate( "新添加的错误消息" ).addConstraintViolation();

             return false ;

         }

         return true ;

     }

}

然后就可以和其他注解一样使用它了

封装

或者是将验证参数的代码提取去出来,单独写一个方法

?

1

2

3

4

5

6

7

8

9

public static void validateParams(Object object) {

     Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); //获取一个验证器

     Set<ConstraintViolation<Object>> violationSet = validator.validate(object); //验证数据,获取到错误集合

     Iterator<ConstraintViolation<Object>> iterator = violationSet.iterator();

     if (iterator.hasNext()) {

         String errorMessage = iterator.next().getMessage(); //获取到错误信息

         throw new ValidationException(errorMessage);

     }

}

当然这里也可以不抛出异常,而返回一个boolean值,如何封装看实际需求

配合Spring使用

?

1

2

3

4

5

6

7

8

@GetMapping ( "/test" )

public Integer lookCanBuyGoods( @Valid JsrTest req, BindingResult result) throws Exception {

     if (result.hasErrors()) {

         throw new ValidationException(result.getAllErrors().get( 0 ).getDefaultMessage());

     }

     //do something...

     return 1 ;

}

@Valid添加这个注解之后就会对参数进行验证,如果在其后没有跟BindingResult,验证不通过就会直接抛出异常,如果添加了BindingResult参数,就不会直接抛出异常,而会把异常信息存储在BindingResult中,供开发者自行处理

如果想要使用分组可以这样

?

1

2

3

4

5

6

7

8

@GetMapping ( "/test" )

public Integer test( @Validated (JsrTest.ValidationGroup. class ) JsrTest req, BindingResult result) throws Exception {

     if (result.hasErrors()) {

         throw new ValidationException(result.getAllErrors().get( 0 ).getDefaultMessage());

     }

     //do something...

     return 1 ;

}

@Validated如果不使用分组其作用和@Valid一致

注解使用说明

Constraint 详细信息
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@PastOrPresent 被注释的元素必须是过去或现在的日期
@Future 被注释的元素必须是一个将来的日期
@FutureOrPresent 被注释的元素必须是将来或现在的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
@Digits(integer =, fraction =) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证
@NotBlank 字符串不能是Null还有被Trim的长度要大于0
@NotEmpty 不能为null,且长度大于0
@Negative 被注释的元素必须是负数
@NegativeOrZero 被注释的元素必须是负数或0
@Positive 必须是正数
@PositiveOrZero 必须是正数或0

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/u012188107/article/details/72770854

查看更多关于Spring 校验(validator,JSR-303)简单实现方式的详细内容...

  阅读:15次