hibernate validator基本使用

引入

Spring-boot

spring-boot-starter-web就包含了hibernate validator。

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring MVC

1
2
3
4
5
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>

验证bean

validator的基本用法和lombok一样。添加到实体类的属性上。如果不符合属性的要求就会抛出错误。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Data
@AllArgsConstructor
public class User {

@NotNull
private String id;

@NotBlank
@Size(max = 20)
private String name;

@NotNull
@Pattern(regexp = "[A-Z][a-z][0-9]")
private String password;

@NotNull
private Integer age;

@Max(10)
@Min(1)
private Integer level;
}

验证

如果不通过spring,validator是无法直接劫持实例化的过程。只能通过对应的validator对象的方法来验证对应的对象。

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
User user = new User(null, "", "123", null, 0);
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();

// 验证所有bean的所有约束
Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
// 验证单个属性
Set<ConstraintViolation<User>> constraintViolations2 = validator.validateProperty(user, "name");
// 检查给定类的单个属性是否可以成功验证
Set<ConstraintViolation<User>> constraintViolations3 = validator.validateValue(User.class, "password", "sa!");

constraintViolations.forEach(constraintViolation -> System.out.println(constraintViolation.getMessage()));
constraintViolations2.forEach(constraintViolation -> System.out.println(constraintViolation.getMessage()));
constraintViolations3.forEach(constraintViolation -> System.out.println(constraintViolation.getMessage()));

结果

1
2
3
4
不能为Null
不能为空
需要匹配正则表达式"[A-Z][a-z][0-9]"
最小为1

验证方法

验证方法可以通过将注解加到对应的位置来验证参数或者返回值。

验证参数

可以通过将注解加到参数前面,然后通过验证器来验证某个方法是是否合法。

例如:

1
2
3
4
5
6
7
8
package org.hibernate.validator.referenceguide.chapter03.parameter; 
public class RentalStation {
public RentalStation(@NotNull String name) { //...
}
public void rentCar( @NotNull Customer customer, @NotNull @Future Date startDate, @Min(1) int durationInDays) {
//...
}
}
  • 验证构造方法的参数不能为空,
  • rentCar方法的第一个参数不为空,
  • 第二个参数必须为当前时间的位来,
  • 第三个参数最小只能为1。

验证返回值

同样的,将注解加到对应的方法上可以验证返回值是否合法。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
package org.hibernate.validator.referenceguide.chapter03.returnvalue; 
public class RentalStation {
@ValidRentalStation
public RentalStation() {
//...
}
@NotNull @Size(min = 1)
public List<@NotNull Customer> getCustomers() {
//...
return null;
}
}

这里确保了:

  • 任何新创建的RentalStation对象都必须满足@ValidRentalStation约束
  • getCustomers()返回的客户列表不能为空,并且必须至少包含1个元素
  • getCustomers()返回的客户列表不能包含空对象。

验证

方法约束的验证是使用ExecutableValidator接口完成的。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Car object = new Car( "Morris" ); Method method = Car.class.getMethod( "drive", int.class );// 1. 获取executableValidator对象
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();

// 2. 验证方法参数
Car object = new Car( "Morris" );
Method method = Car.class.getMethod( "drive", int.class );
Object[] parameterValues = { 80 };
Set<ConstraintViolation<Car>> violations = executableValidator.validateParameters( object, method, parameterValues);

Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation()
.annotationType();

// 3. 验证返回值
Constructor<Car> constructor = Car.class.getConstructor( String.class, String.class );
Car createdObject = new Car( "Morris", null );
Set<ConstraintViolation<Car>> violations = executableValidator .validateConstructorReturnValue( constructor, createdObject);

Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation().annotationType();

注意:ExecutableValidator接口总共提供了四个方法:

  • validateParameters():用来验证方法参数。
  • validateReturnValue():用来验证方法返回值。
  • validateConstructorParameters():用来验证构造器参数。
  • validateConstructorReturnValue():用来验证构造器返回值。

spring结合

可以看到,上面的验证非常复杂,但是有了spring的aop帮助,我们只需要配置以下,就可以让spring自动为我们进行验证。我们只需要在方法或者参数上添加约束注解即可。

class方式

基本配置

如果只需要验证实体类的约束,则只需要配置一个validator即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class ValidatorConfig {

/**
* 配置验证器
*
* @return validator
*/
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
// 快速失败模式
.failFast(true)
// .addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
return validatorFactory.getValidator();
}
}

可以通过方法 failFast(true)addProperty("hibernate.validator.fail_fast", "true")设置为快速失败模式,快速失败模式在校验过程中,当遇到第一个不满足条件的参数时就立即返回,不再继续后面参数的校验。否则会一次性校验所有参数,并返回所有不符合要求的错误信息

方法验证配置

如果需要验证方法参数和返回值,则还需要配置另一个对象。

1
2
3
4
5
6
7
8
9
10
/**
* 设置方法参数验证器
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
// 设置validator模式为快速失败返回
postProcessor.setValidator(validator());
return postProcessor;
}

XML方式

同样的,在XML中也只需要配置这两个对象即可完成配置。

基本配置

1
2
3
4
5
6
7
8
<!-- validator基本配置 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 映射资源文件 -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>

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

方法验证配置

1
2
3
4
<!-- 设置方法参数验证器 -->
<bean id="methodValidationPostProcessor" class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator"/>
</bean>

使用

在配置好之后,只要是在spring容器中的对象,都可以让spring自动完成验证。

请求接口验证对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
public class UserController {
@PostMapping("/login1")
public void login1(@Valid @RequestBody User user){
//如果有错误会直接抛出。
//...
}

@PostMapping("/login2")
public void login1(@Valid @RequestBody User user, BindingResult result){
// 在控制器内本地处理验证错误
if (result.hasErrors()) {
result.getAllErrors().forEach(s -> System.out.println(s.getDefaultMessage()));
return R.fail(result.getAllErrors().get(0).getDefaultMessage());
}
//...
}
}

一般都是使用第一种方式,然后通过springMVC全局处理异常。

请求验证简单类型

这里必须有两步:

  1. 必须要配置methodValidationPostProcessor
  2. 必须在类上加@Validated注解。

例:

1
2
3
4
5
6
7
8
9
@Validated
@RestController
public class UserController {

@PostMapping("/login2")
public void checkEmail(@Email String email){
//...
}
}

注解分类

validator-api-2.0的约束注解有22个,具体我们看下面表格

空与非空检查

注解 支持Java类型 说明
@Null Object 为null
@NotNull Object 不为null
@NotBlank CharSequence 不为null,且必须有一个非空格字符
@NotEmpty CharSequence、Collection、Map、Array 不为null,且不为空(length/size>0)

Boolean值检查

注解 支持Java类型 说明 备注
@AssertTrue boolean、Boolean 为true 为null有效
@AssertFalse boolean、Boolean 为false 为null有效

日期检查

注解 支持Java类型 说明 备注
@Future Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间之后 为null有效
@FutureOrPresent Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间或之后 为null有效
@Past Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间之前 为null有效
@PastOrPresent Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间或之前 为null有效

数值检查

注解 支持Java类型 说明 备注
@Max BigDecimal、BigInteger,byte、short、int、long以及包装类 小于或等于 为null有效
@Min BigDecimal、BigInteger,byte、short、int、long以及包装类 大于或等于 为null有效
@DecimalMax BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 小于或等于 为null有效
@DecimalMin BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 大于或等于 为null有效
@Negative BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 负数 为null有效,0无效
@NegativeOrZero BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 负数或零 为null有效
@Positive BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 正数 为null有效,0无效
@PositiveOrZero BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 正数或零 为null有效
@Digits(integer = 3, fraction = 2) BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 整数位数和小数位数上限 为null有效

其他

注解 支持Java类型 说明 备注
@Pattern CharSequence 匹配指定的正则表达式 为null有效
@Email CharSequence 邮箱地址 为null有效,默认正则 '.*'
@Size CharSequence、Collection、Map、Array 大小范围(length/size>0) 为null有效

hibernate-validator扩展约束(部分)

注解 支持Java类型 说明
@Length String 字符串长度范围
@Range 数值类型和String 指定范围
@URL URL地址验证

另外还可以自定义约束注解,此处为简单介绍,就不再赘述。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :