赞
踩
创建时勾选 I/O -> Validation,也可以手动添加依赖
<!-- 这个依赖主要包含了 hibernate-validator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
实质是使用hibernate的遗产 hibernate-validator,也可以直接引入下面的依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.2.Final</version>
</dependency>
一个字段上可以标注多个校验注解
@RestController
@Validated //类上加 @Validated
public class TestController {
@RequestMapping("test") //直接在参数前加校验注解
public String test(@NotBlank(message = "email不能为空") @Email(message = "email格式错误") String email,
@NotBlank(message = "密码不能为空") String password, Integer gender,
@Past(message = "生日只能是过去的日期") Date birthday) {
return "ok";
}
}
不满足校验时抛出 ValidationException,如果不捕获处理,接口直接报500;可以在全局异常处理器中统一捕获处理,e.getMessage() 拿到的message即校验校验注解的message属性值。
@RestController
//类上不用加什么校验注解
public class TestController {
@RequestMapping("test") //在要校验的实体类参数前面加 @Valid,此处也可以使用 @Validated
public String test(@Valid UserVO userVO) {
return "ok";
}
}
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class UserVO implements Serializable { private static final long serialVersionUID = 2199611382183141716L; @NotBlank(message = "email不能为空") @Email(message = "email格式错误") private String email; @NotBlank(message = "密码不能为空") private String password; private Integer gender; @Past(message = "生日只能是过去的日期") private Date birthday; }
往往都是使用实体类接收参数,自动校验
所以很多时候都需要进行手动校验。
参数校验工具类
import org.apache.commons.collections.CollectionUtils; import org.hibernate.validator.HibernateValidator; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 参数校验工具类 */ public class ValidationUtils { /** * 默认校验器,使用默认校验配置 * 校验器有多种实现,hibernate校验器只是其中一种实现 */ private static final Validator defaultValidator = Validation.buildDefaultValidatorFactory().getValidator(); /** * 以上代码也可以这样写 */ private static final Validator defaultValidator1 = Validation.byDefaultProvider() .configure() .buildValidatorFactory().getValidator(); /** * hibernate默认校验器 */ private static final Validator hibernateDefaultValidator = Validation.byProvider(HibernateValidator.class) .configure() .buildValidatorFactory().getValidator(); /** * hibernate快速失败校验器 */ private static final Validator hibernateFailFastValidator = Validation.byProvider(HibernateValidator.class) .configure().failFast(true) .buildValidatorFactory().getValidator(); /** * 隐藏构造器 */ private ValidationUtils() { } /** * 快速校验参数 * * @param t 需要校验的参数 * @param <T> 泛型,即要校验的参数类型 * @return 错误提示信息。通过校验返回null,不通过校验则返回第一个错误字段的提示信息 */ public static <T> String validateFastFail(T t) { if (t == null) { return "the input parameter is null"; } //校验参数,返回错误信息集合,通过校验时返回空集合(不为null) //因为这个校验器启用了快速失败模式,遇到第一个错误字段就返回,所以这个集合中最多只有一个元素 Set<ConstraintViolation<T>> constraintViolations = hibernateFailFastValidator.validate(t); if (CollectionUtils.isEmpty(constraintViolations)) { return null; } return constraintViolations.iterator().next().getMessage(); } /** * 校验参数 * * @param t 要校验的参数 * @param <T> 泛型,即要校验的参数类型 * @return 错误提示信息集合,通过校验返回空集合 */ public static <T> List<String> validate(T t) { if (t == null) { return Collections.emptyList(); } Set<ConstraintViolation<T>> constraintViolations = hibernateDefaultValidator.validate(t); return constraintViolations.stream() .map(ConstraintViolation::getMessage) .collect(Collectors.toList()); } }
在方法体中手动调用方法进行校验,无需在实体参数前加 @Valid
均可指定message属性值,建议都指定message,返回的错误提示比默认值更友好
//不能为null,可校验任何类型
@NotNull
//不能是null、empty,可校验CharSequence、数组、集合
@NotEmpty
//不能是null、blank,可校验CharSequence
@NotBlank
//校验数值型的值大小,可校验 大数(BigDecimal、BigInteger)、各类整型及对应的包装类型(byte、short、int、long) //由于浮点数(float、double)存在精度问题,暂不支持 @Max(100) //<=,最大值不能超过100,此处省略属性名value @Min(10) @Range(min = 10, max = 100) //相当于@Min+@Max //校验数值大小,可校验 大数(BigDecimal、BigInteger)、各类整型及对应的包装类型(byte、short、int、long)、CharSequence //不要误以为名称中的Decimal是指定点;由于浮点数(float、double)存在精度问题,暂不支持 //value指定最值 String形式,inclusive可选 指定是否包含、是否可以取等,默认true @DecimalMax(@DecimalMax(value = "100.00", inclusive = false) @DecimalMin(value = "100.00", inclusive = false) //校验数值位数,可校验 大数(BigDecimal、BigInteger)、各类整型及对应的包装类型(byte、short、int、long)、CharSequence //integer指定整数部分最多4位,fraction指定小数部分最多2位 @Digits(integer = 4, fraction = 2) //校验日期时间点,可校验jdk自带的各种日期、时间类型 @Future //必须是未来的时间点 @Past //必须是过去的时间点 //校验字符串长度,只能校验字符串,字符串长度(length)只能在 [5,10] 区间上 @Length(min = 5, max = 10) //校验数组、集合、CharSequence的元素个数,元素个数只能在 [5,10] 区间上。CharSequence即字符个数 @Size(min = 5, max = 10) //校验字符串内容,必须是指定格式 @Email //hibernate-validator自身的 @Email 已经过时,这是 hibernate-validator 引入的 jakarta.validation-api 中的注解 @URL //默认允许任何协议、任何host、任何端口号,注意内容不能省略http、https、ftp之类的协议,必须是完整的url @URL(protocol = "http", host = "www.baidu.com")
以上注解只校验内容,在值不为空时才会校验内容,也就是说空值会通过校验。如果要校验非空,还需要加上@NotNull
、@NotBlank
、@NotEmpty
之类的注解。
可以用正则表达式进行校验,示例
@Pattern(regexp = "^[1][3-9][0-9]{9}$", message = "手机号为空或格式错误")
@Controller
@Validated
public class TestController {
@RequestMapping("/handler")
@ResponseBody
//要校验的参数是实体类
public User handler( @Validated User user) {
//.....
return user;
}
}
@Data
public class User implements Serializable {
//......
@Valid //加@Valid
private GoodsCar goodsCar;
@Valid //加@Valid
private List<Order> orderList;
}
spring的 @Validated 不支持多级嵌套校验,Validation的 @Valid 则支持。
如果要检验的参数是实体类,而这个实体类中又嵌套了实体类,如果要校验内嵌的实体类中的成员变量,还需要在内嵌的实体类成员上加@Valid。@Valid修饰的成员为null时,不会使用该实体中的校验注解进行校验;只有修饰的成员不为null时,才会使用该实体中的校验注解进行校验。
多个方法都要使用某个实体类作为参数,但对这个实体类的成员变量的校验规则不同,这时可以使用分组校验。
/**
* 定义一个类|接口作为一个分组,不一定要继承validation的Default
* 也可以直接使用已存在的类|接口作为分组
*/
public interface OperateById {
}
public interface FindByUser extends Default {
}
@Getter @Setter @ToString public class User implements Serializable { //使用groups指定该字段所属的分组,属于多个组时写成数组形式 @NotNull(groups = {OperateById.class, FindByUser.class}) private Integer id; @NotBlank(groups = FindByUser.class) private String name; //如果缺省groups属性,默认为Default.class,属于默认分组 @Pattern(regexp = "[0-9]{11}") private String tel; }
@Controller
@Validated
public class TestController {
@RequestMapping("/handler")
@ResponseBody
//校验时指定所使用的校验规则(分组),可简写为 @Validated(FindByUser.class)。缺省value属性时默认为Default.class,使用默认分组
public User handler( @Validated(value = FindByUser.class) User user) {
//.....
return user;
}
}
校验时会使用指定分组中的校验规则进行校验。示例中
自定义的分组要不要继承Default,视需求而定。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。