大綱:
- 參數校驗
- ConstraintValidator自定義驗證
一、參數驗證
@NotNull 就是參數必傳
javax.validation.constraints下面有許多注解不一一贅述、字面意思也很清晰。
import lombok.Data; import javax.validation.constraints.NotNull; /** * Created by lby on 2019/6/21. */ @Data public class Person { private String name; @NotNull private String age; }
1.1注解驗證
@Validated注解加到需要驗證的請求對象上
@RequestMapping("/hello") public String hello(@RequestBody @Validated Person person, BindingResult result){ if(result.hasErrors()){ List<FieldError> fieldErrors = result.getFieldErrors(); fieldErrors.forEach(item->{ System.out.println(item.getDefaultMessage()); }); } return person.getName()+person.getAge(); }
未通過的驗證信息會存放到BindingResult對象中。
1.2獲取SmartValidator進行驗證
SmartValidator在spring初始化完成的時候已經在ioc容器里了
@Autowired SmartValidator validator; @RequestMapping("/hello") public String hello(@RequestBody Person person){ BindingResult result = new BeanPropertyBindingResult(person,person.getClass().getSimpleName()); validator.validate(person,result); if(result.hasErrors()){ result.getAllErrors().forEach(item->{ System.out.println(item.getDefaultMessage()); }); } return person.getName()+person.getAge(); }
1.3分組校驗
定義分組:定義兩個內部接口A和B就是2個組別。
校驗分組:修改一下Person對象上的校驗注解加上groups,groups里面的內容就是需要校驗的組。
例:下例中需中如果校驗A組則name、age都要NotNull,如果校驗B則只要nameNotNull
@Data public class Person { @NotNull(groups = {A.class,B.class}) private String name; @NotNull(groups = {A.class}) private String age; public interface A{} public interface B{} }
注解校驗:
@RequestBody @Validated(value = { Person.A.class}) Person person,
與之前的區別就是在@Validated中填入了需要校驗的組(參數為一個數組),上例中校驗A組。
smartValidatior校驗:
validator.validate(person,result,Person.A.class);
與之前的區別就是validate方法傳入了第三個參數來標識需要驗證的組(參數為一個數組)上例中校驗A組。
二、ConstraintValidator自定義驗證
定義一個驗證類實現ConstraintValidator接口
public class EnumValidImpl implements ConstraintValidator<EnumValid,String> { private String[] values; private String message; @Override public void initialize(EnumValid constraintAnnotation) { //拿待驗證字段注解上的信息 values = constraintAnnotation.value(); message = constraintAnnotation.message(); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { //value就是需要校驗的值 //驗證 boolean exist = false; for (String evalue : values) { if(value.equals(evalue)){ exist = true; break; } } //報錯信息 if (StringUtils.isBlank(message)) { StringBuilder sb = new StringBuilder(); for (String s : values) { sb.append(s).append(";"); } String msg = sb.toString(); msg = msg.substring(0,msg.length()-1); //替換原來的報錯信息 context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("value must in:"+msg).addConstraintViolation(); } return exist; } }
自定義注解用於待校驗的屬性上
@Constraint(validatedBy = {EnumValidImpl.class })//指定這個校驗注解的實現類 @Target({ ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface EnumValid { String[] value(); String message() default "默認報錯消息"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
用法:
@Data public class Person { @EnumValid({"aa","bb"}) private String name; private String age; }
我自定義的注解意思:name只能為aa,bb