在项目的开发中,在后台接口中,我们经常需要对前端传来的数据进行校验,一般都是使用@Valid注解,但是有的时候我们的校验工作比较复杂,@Valid提供的注解无法满足我们的需求,这个时候我们就需要自己来定义我们自己所需的Valid注解。有同学不清楚@Valid注解的可以看一下我的另一篇文章Spring的数据校验。
首先我们来定义一个接口来实现我们的@Valid注解
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyConstraintValidator.class)
public @interface MyConstraint {
String message() ;
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
其中:@Target —— 表示这个注解可以作用在什么地方,例如作用在方法上,或作用在某个字段上。
@Retention —— 被它所注解的注解保留多久,runtime表示不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Constraint —— 表示我们判断逻辑的具体实现类是什么。
再来定义我们的具体实现类的代码:
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Object> {
@Override
public void initialize(MyConstraint constraintAnnotation) {
System.out.println("my validator init");
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
String name = (String)value;
if ("tom".equals(name)) {
return true;
}
System.out.println(value);
return false;
}
}
其中实现的ConstraintValidator接口中的两个参数,第一个参数就我们定义的接口,第二个参数表示这个注解作用在什么类型的字段上,比如:我们这个定义的注解是只作用在String类型时,可以将Object改成String。
现在就可以将我们自定义的注解作用在我们需要校验的字段上了
public class User {
@MyConstraint(message = "这是一次测试")
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
编写我们的Controller进行数据接收
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping
public void create(@Valid @RequestBody User user,BindingResult errors) {
if (errors.hasErrors()) {
errors.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage()));
}
}
当我们传入username为tom时,控制台不打印信息,当username不是tom时,控制台打印出message中的信息,即“这是一次测试”。