背景
在web服务接口调用时,会有各种各样的输入参数,为了避免错误参数导致接口垮掉,我们需要为入参先做各种判断,当参数合格后,才放行后续操作。那我们代码里就会有很多业务不相关的代码,并且每个接口都要写,一点都不优雅。因此,我们引入了validation
,通过添加@NotNull
,@NotEmpty
等注解进行参数校验,参数不合法的调用请求根本就不给进入到方法的机会。
常用的注解有两个来源,一个是java自带的javax.validation
包,一个是hebernate的org.hibernate.validator.constraints
包,后者是基于前者的加强版,提供了更多高效的注解。
加入依赖
springboot中有专门的起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
改造Controller
想要对方法的参数进行校验,需要对方法所在的类添加@Validated
注解,springboot文档中有一句话:
Target classes with such annotated methods need to be annotated with the @Validated annotation at the type level for their methods to be searched for inline constraint annotations
也就是说只有添加了该注解,类中的方法的校验注解才能被发现并生效。
@Validated
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/valid")
@ResponseBody
public String valid(@NotNull(message = "不能为null") String name){
return "name";
}
}
创建了上面的接口后,不传入name
参数时:
localhost:8080/test/valid
会返回结果:
{
"timestamp": "2018-06-05T14:31:43.039+0000",
"status": 500,
"error": "Internal Server Error",
"message": "valid.name: 不能为null",
"path": "/test/valid"
}
其中message
中的内容就是我们在j@NotNull
注解中设置的提示信息。
注解详解
空判断
@NotNull
: 仅判断是否为Null,不判断空@NotBlank
:仅用于字符串,判断Null,以及去除前后空格后是否为空@NotEmpty
:判断Null,并且判断是否为空,包括字符串是否为空,和集合是否为空
数值判断
@Min
:判断数值最小值@Max
:判断数值最大值
递归判断
@Valid
: 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
自定义校验注解
创建注解器
实现ConstraintValidator
接口,并实现校验方法isValid()
public class DemoValidator implements ConstraintValidator<MyGate,String> {
private String regexp;
private String message;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
boolean isValied = false;
if(StringUtils.isEmpty(value)){
message = "不能为空";
}
if(StringUtils.isEmpty(regexp)){
message = "正则不能为空";
}
if(value.matches(regexp)){
isValied = true;
}
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
return isValied;
}
@Override
public void initialize(MyGate constraintAnnotation) {
this.regexp = constraintAnnotation.regexp();
this.message = constraintAnnotation.message();
}
}
创建注解
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {DemoValidator.class})
public @interface MyGate {
String message() default "mygate";
String regexp();
Class<?>[] groups() default {};
Class<?>[] payload() default {};
}
现在就可以直接在参数上添加@MyGate
注解来校验数据了,可以自定义正则表达式和错误提示信息。