springboot中使用Validation
(一)常用注解
//开启验证,标注在待验证的Object对象上
@Valid
//标注在待验证的字段上
@NotNull
@Null
@Size
@Min
@Max
(二)具体使用
1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2、创建待验证的Object,并添加验证注解
public class Person {
/**
* @PersonName(prefix = "潘"):自定义注解
*/
@NotNull
@PersonName(prefix = "潘")
private String name;
@Min(value = 12)
@Max(value = 30, message = "超过30岁的不要!")
private Integer age;
}
3、创建自定义校验注解类@PersonName
备注:
重点一:所有的自定义注解类都可以参照下面的类创建。
重点二:必须注意@Constraint注解,绑定具体的校验实现类
/**
* 自定义校验注解
* @author 咸鱼
* @date 2018/10/14 17:57
* 重点:使用@Constraint(validatedBy = {PersonNameConstraintValidator.class})绑定具体的校验实现类
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(PersonName.List.class)
@Documented
@Constraint(validatedBy = {PersonNameConstraintValidator.class})
public @interface PersonName {
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
/**
* 定义名字必须以**前缀开始
*/
String prefix() default "";
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List {
PersonName[] value();
}
}
4、创建自定义校验注解的具体实现类
/**
* ConstraintValidator<PersonName, String>:
* 泛型一:校验的注解类
* 泛型二:被校验的对象类型
*/
public class PersonNameConstraintValidator implements ConstraintValidator<PersonName, String> {
private String prefix;
/**
* @param constraintAnnotation 待校验注解的所有信息
*/
@Override
public void initialize(PersonName constraintAnnotation) {
//取出注解中的数据
this.prefix = constraintAnnotation.prefix();
}
/**
* 在这里面定义校验规则
* @param value 待校验对象
* @param context
* @return true 通过校验 false 无法通过校验
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//校验规则为:名字必须以#{prefix}开头
if (!value.startsWith(prefix)){
/**
* 自定义校验错误信息
*/
context.disableDefaultConstraintViolation();
ConstraintValidatorContext.ConstraintViolationBuilder builder =
context.buildConstraintViolationWithTemplate("人的名字必须以\"" + prefix + "\"起始");
builder.addConstraintViolation();
return false;
}
return true;
}
}
5、使用案例
/**
* 开启校验注解:@Valid
*/
@RestController
public class PersonController {
@PostMapping("/person")
public Person savePerson(@Valid @RequestBody Person person){
return person;
}
}
(三)校验拓展,统一异常处理
问题:以上的案例,当无法通过校验时,会返回400错误,但是我们一般都会做全局异常处理,返回400错误,将导致我们没法统一处理这个异常?
解决办法:
当无法通过校验时,校验结果会存到BindingResult对象中,我们可以通过该对象截取校验信息,然后将该异常抛出去,进行统一异常处理。
/**
* 增
* “@Valid”开启校验
* BindingResult:存放校验结果
*/
@PostMapping("/girls")
public Girl addGirl(@Valid Girl girl, BindingResult bindingResult){
//若不符合约束
if (bindingResult.hasErrors()){
//获取不符合约束时,自定义的异常信息
throw new **Exception(bindingResult.getFieldError().getDefaultMessage());
}
return girlService.addGirl(girl);
}