@Validated和@Valid配合可以进行对象的深层次校验。
@Valid 作用在方法,字段,构造器和参数上
@Validated 作用在类 方法 和参数上
当我们的接口参数中包含深层次的对象时 如:
BaseInfo时公共对象,字段含有校验的逻辑
@Data
public class BaseInfo{
@NotEmpty(message="名称不能为空")
private String name;
@NotNull(message="年龄不能为空")
private Integer age;
@SexValidator //自定义校验逻辑
private Integer sex;
}
Person为接口接收对象,属性中包含BaseInfo。
@Data
public class Person{
//@Vlid表示对bseInfo要进行校验
@Valid
private BaserInfo baseInfo;
@NotEmpty(message="年龄不能为空")
private String localtion;
}
@RestController
public class testController{
@PostMappering("/postTest")
public void postTest(@Validated @RequestBody Person person){
.......
}
}
对于接口输入参数的一般属性。使用@Validated就可以验证。但是如果属性是自定义的对象类型。则需要加入@Valid 才能做到深层次的校验。
javax.validation.constraints 中包含了基本的字段校验逻辑。但是有时候我们需要自定义的逻辑。自定义的教育你需要实现ConstraintValidator接口。
public interface ConstraintValidator {
/**
* 初始化方法。
* 在使用此实例进行验证之前调用此方法
* 可以不实现
*
*/
default void initialize(A constraintAnnotation) {
}
/**
* 验证方法
*/
boolean isValid(T value, ConstraintValidatorContext context);
}
依赖:
javax.validation
validation-api
2.0.1.Final
先自定义一个注解:如ListValidator和 EquaValidator:
首先是数组校验:
/**
* 数组校验注解
*/
@Documented
//执行校验的类(j校验器)
@Constraint(
validatedBy = {ListValidator.class}
)
//注解的使用场景
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
//默认消息的路径
String message() default "{com.atguigu.common.validator.ListValue.message}";
//分组信息
Class>[] groups() default {};
//负载
Class extends Payload>[] payload() default {};
//注解携带的数据
int[] values() default {};
}
/**
*自定义数组校验方法
*/
public class ListValidator implements ConstraintValidator {
private Set set = new HashSet();
//初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
int[] value = constraintAnnotation.values();
if (value.length>0){
for (int i : value) {
set.add(i);
}
}
}
//校验方法
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(integer);
}
}
相等校验:EqualValidtor:
@Documented
@Constraint(validatedBy = {EqualsValidator.class})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface EqualsValue {
String message() default "必须是xzh";
String value default null;
Class>[] groups() default { };
Class extends Payload>[] payload() default { };
}
public class EqualsValidator implements ConstraintValidator {
String defaultValue = null;
@Override
public void initialize(ListValue constraintAnnotation) {
value = constraintAnnotation.value();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(defaultValue != null && value != null ){
return defaultValue.equals(value);
}
}
}
之后我们就可以在自己需要校验的属性中配置校验数据了
@Data
public class BaseInfo{
@NotEmpty(message="名称不能为空")
private String name;
@NotNull(message="年龄不能为空")
private Integer age;
@SexValidator //自定义校验逻辑
private Integer sex;
@ListValue(values={1, 2, 3}, maessage="数组参数必须是1,2,3")
private Integer lists;
@EqualValue(value="123", message="数据必须是123")
private String equalsValue;
}
参数校验不匹配会抛出异常org.springframework.web.bind.MethodArgumentNotValidException。我们可以在自定义的拦截器中拦截即可