springboot使用hibernate validator校验
2018-02-07 16:43
471 查看
一、参数校验
在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦:验证代码繁琐,重复劳动
方法内代码显得冗长
每次要看哪些参数验证是否完整,需要去翻阅验证逻辑代码
hibernate validator(官方文档)提供了一套比较完善、便捷的验证实现方式。
spring-boot-starter-web包里面有
hibernate-validator包,不需要引用hibernate validator依赖。
二、hibernate validator校验demo
先来看一个简单的demo,添加了Validator的注解:import org.hibernate.validator.constraints.NotBlank; import javax.validation.constraints.AssertFalse; import javax.validation.constraints.Pattern;
View Code
如上Person所示,3个分组分别验证字段如下:
GroupA验证字段userId;
GroupB验证字段userName、sex;
Default验证字段age(Default是Validator自带的默认分组)
a、分组
只验证GroupA、GroupB标记的分组:@RequestMapping("/demo5") public void demo5(){ Person p = new Person(); /**GroupA验证不通过*/ p.setUserId(-12); /**GroupA验证通过*/ //p.setUserId(12); p.setUserName("a"); p.setAge(110); p.setSex(5); Set<ConstraintViolation<Person>> validate = validator.validate(p, GroupA.class, GroupB.class); for (ConstraintViolation<Person> item : validate) { System.out.println(item); } }
或
@RequestMapping("/demo6") public void demo6(@Validated({GroupA.class, GroupB.class}) Person p, BindingResult result){ if(result.hasErrors()){ List<ObjectError> allErrors = result.getAllErrors(); for (ObjectError error : allErrors) { System.out.println(error); } } }
GroupA、GroupB、Default都验证不通过的情况:
验证信息如下所示:ConstraintViolationImpl{interpolatedMessage='必须在[4,20]', propertyPath=userName, rootBeanClass=class validator.demo.project.model.Person, messageTemplate='必须在[4,20]'}
ConstraintViolationImpl{interpolatedMessage='必须大于0',
propertyPath=userId, rootBeanClass=class
validator.demo.project.model.Person, messageTemplate='必须大于0'}
ConstraintViolationImpl{interpolatedMessage='性别必须在[0,2]',
propertyPath=sex, rootBeanClass=class
validator.demo.project.model.Person, messageTemplate='性别必须在[0,2]'}
GroupA验证通过、GroupB、Default验证不通过的情况:
验证信息如下所示:ConstraintViolationImpl{interpolatedMessage='必须在[4,20]',
propertyPath=userName, rootBeanClass=class
validator.demo.project.model.Person, messageTemplate='必须在[4,20]'}
ConstraintViolationImpl{interpolatedMessage='性别必须在[0,2]',
propertyPath=sex, rootBeanClass=class
validator.demo.project.model.Person, messageTemplate='性别必须在[0,2]'}
b、组序列
除了按组指定是否验证之外,还可以指定组的验证顺序,前面组验证不通过的,后面组不进行验证:指定组的序列(GroupA》GroupB》Default):
@GroupSequence({GroupA.class, GroupB.class, Default.class}) public interface GroupOrder { }
测试demo:
@RequestMapping("/demo7") public void demo7(){ Person p = new Person(); /**GroupA验证不通过*/ //p.setUserId(-12); /**GroupA验证通过*/ p.setUserId(12); p.setUserName("a"); p.setAge(110); p.setSex(5); Set<ConstraintViolation<Person>> validate = validator.validate(p, GroupOrder.class); for (ConstraintViolation<Person> item : validate) { System.out.println(item); } }
或
@RequestMapping("/demo8") public void demo8(@Validated({GroupOrder.class}) Person p, BindingResult result){ if(result.hasErrors()){ List<ObjectError> allErrors = result.getAllErrors(); for (ObjectError error : allErrors) { System.out.println(error); } } }
GroupA、GroupB、Default都验证不通过的情况:
验证信息如下所示:ConstraintViolationImpl{interpolatedMessage='必须大于0', propertyPath=userId, rootBeanClass=class validator.demo.project.model.Person, messageTemplate='必须大于0'}
GroupA验证通过、GroupB、Default验证不通过的情况:
验证信息如下所示:ConstraintViolationImpl{interpolatedMessage='必须在[4,20]', propertyPath=userName, rootBeanClass=class validator.demo.project.model.Person, messageTemplate='必须在[4,20]'}
ConstraintViolationImpl{interpolatedMessage='性别必须在[0,2]',
propertyPath=sex, rootBeanClass=class
validator.demo.project.model.Person, messageTemplate='性别必须在[0,2]'}
结论:分组顺序校验时,按指定的分组先后顺序进行验证,前面的验证不通过,后面的分组就不行验证。
五、自定义验证器
一般情况,自定义验证可以解决很多问题。但也有无法满足情况的时候,此时,我们可以实现validator的接口,自定义自己需要的验证器。如下所示,实现了一个自定义的大小写验证器:
public enum CaseMode { UPPER, LOWER; } @Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) @Documented public @interface CheckCase { String message() default ""; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; CaseMode value(); } public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private CaseMode caseMode; public void initialize(CheckCase checkCase) { this.caseMode = checkCase.value(); } public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { if (s == null) { return true; } if (caseMode == CaseMode.UPPER) { return s.equals(s.toUpperCase()); } else { return s.equals(s.toLowerCase()); } } }
要验证的Model:
public class Demo{ @CheckCase(value = CaseMode.LOWER,message = "userName必须是小写") private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
validator配置:
@Bean public Validator validator(){ ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) .configure() .addProperty( "hibernate.validator.fail_fast", "true" ) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); return validator; }
验证测试:
@RequestMapping("/demo4") public void demo4(){ Demo demo = new Demo(); demo.setUserName("userName"); Set<ConstraintViolation<Demo>> validate = validator.validate(demo); for (ConstraintViolation<Demo> dem : validate) { System.out.println(dem.getMessage()); } }
输出结果:
userName必须是小写
六、常见的注解
Bean Validation 中内置的 constraint@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
//大于0.01,不包含0.01 @NotNull @DecimalMin(value = "0.01", inclusive = false) private Integer greaterThan; //大于等于0.01 @NotNull @DecimalMin(value = "0.01", inclusive = true) private BigDecimal greatOrEqualThan; @Length(min = 1, max = 20, message = "message不能为空") //不能将Length错用成Range //@Range(min = 1, max = 20, message = "message不能为空") private String message;
七、参考资料
参考资料:http://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html_single/#validator-gettingstarted
相关文章推荐
- Spring boot 使用 shiro做安全校验
- SpringBoot 中使用声明式注解简化参数校验
- 关于怎么解决从ajax传入的json参数注入到Controller的接收对象 以及如何在Spring Boot项目使用参数校验
- 详解如何在Spring Boot项目使用参数校验
- springboot 使用校验框架validation校验
- Spring Boot项目使用参数校验
- 如何在Spring Boot项目使用参数校验
- Kotlin & Spring boot 使用@Valid校验无效解决方法
- springboot使用hibernate validator校验方式
- springboot使用hibernate validator校验方式
- Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化
- springboot使用hibernate validator校验
- springboot使用Validator校验方式
- 使用SpringBoot通过自定义注解+AOP+全局异常处理实现参数统一非空校验
- springboot使用hibernate validator校验
- 如何在Spring Boot项目使用参数校验
- SpringBoot (六) :如何优雅的使用 mybatis
- Spring Boot教程(六) -- 使用 Spring Boot CLI
- Spring Boot 中使用 SolrCloud
- SpringBoot是使用socket注解式