1 Validator作用
提高 spring mvc http 参数校验开发效率,有效避免如下复杂代码使用:
if(StringUtils.isBlank(name)){
return new ReponseEntity(HttpStatus.BAD_REQUEST);
}
2 配置校验器,发现错误立即返回,可以减少无效校验
@Configuration
public class ValidationConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
@Bean
public static Validator validator() {
return Validation
.byProvider(HibernateValidator.class)
.configure()
//快速返回模式,有一个验证失败立即返回错误信息
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}
3 配置全局controller异常拦截器,参数检查异常以比较统一的形式返回
@ControllerAdvice
public class ValidatorExceptionHandler {
/**
* 在实体中使用注解校验异常拦截
* @param exception
* @return
*/
@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handle(MethodArgumentNotValidException exception) {
return exception.getBindingResult().getAllErrors();
}
/**
* controller接口方法中校验异常拦截
* @param exception
* @return
*/
@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handle(ConstraintViolationException exception) {
return exception.getConstraintViolations().stream().map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
}
}
4 单个参数验证
@GetMapping("/list")
public ResponseEntity list(@RequestParam("name") @Validated @NotBlank String name){
}
5 分组验证
5.1创建空的interface接口
public interface RoleUpdateGroup{
}
publica interface RoleAddGroup{
}
public class RoleDTO {
@NotNull(groups = {RoleUpdateGroup.class})
private Long id;
@NotNull(groups = {RoleUpdateGroup.class, RoleAddGroup.class})
@Length(groups = {RoleUpdateGroup.class, RoleAddGroup.class} , min = 3, max = 10, message = "角色名称在3-10位之间")
private String roleName;
@NotNull
private Integer age【注】age没有指定自定义分组,自动属于Default.class默认组
}
5.2 分组校验有两种互斥的
1)
@GroupSequence + @Validated 【注】@Validated本身groups不起效
@GroupSequence({RoleAddGroup.class, RoleUpdateGroup.class, RoleDTO.class})
class RoleDTO {
}
@PostMapping(value = "/add")
public ResponseEntity add(@Validated @RequestBody RoleDTO roleDTO){
}
按照顺序 RoleAddGroup.class -> RoleUpdateGroup.class -> Default.class
2)
@Validated(Group.class) 【注】仅使用@Validated
@PostMapping(value = "/add")
public ResponseEntity add(@Validated(RoleAddGroup.class) @RequestBody RoleDTO roleDTO){
}
仅仅检查RoleAddGroup.class组的属性,如果检查时不指定组group,则只检查默认组Default.class组的age属性
【注】当RoleDTO 指定@GroupSequence后,会覆盖@Validated(RoleAddGroup.class)的分组检查效果
6 自定义验证
(1)自定义脚本
// 必须要关联自定义的validator处理器MyValidator
@Constraint(validatedBy = MyValidator.class)
@Target( { java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD })
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
public @interface MyValidate {
//提示信息,可以写死,可以填写国际化的key
String message() default "{Cannot.contain.Spaces}";
int length() default 5;
//下面这两个属性必须添加
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
(2)自定义校验处理器
// 关联自定义的注解
public class MyValidator implements ConstraintValidator<MyValidate, String> {
private int length;
// 初始化,MyValidator实例化时候执行调用一次
@Override
public void initialize(MyValidate myValidate) {
length = myValidate.length();
}
// s 就是你请求绑定到参数的值
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return false;
}
}
7 @Validated Vs. @Valid
@Validated 支持分组group,但不能支持验证POJO的属性
@Valid不支持分组,但支持POJO属性验证,进一步完成嵌套对象的验证,如:
两者都可以放在方法的参数、类上
fun(@Valid UserDTO user) 正确
fun(@Validated(grroups={Grp1.class,Grp2.class}) UserDTO user) 正确
class UserDTO {
@Valid
Address address
}
正确
@Valid是标准的JSR-303规范,@Validated是JSR-303规范变种,并增加一些扩展功能