Hibernate-validator是springmvc中对于控制层的参数进行校验的常用工具,有些特殊情况下,自带的校验器可能不满足我们的场景需要,且此类校验在业务场景下比较常见,一种选择就是进行自定义扩展校验注解。
假设:我们需要校验一个字段的值是某几个特定的值(当然用正则也能实现,这里用这个案例来演示如何扩展)
1. 增加自定注解Include和校验器IncludeValidator
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(Include.List.class)
@Documented
@Constraint(validatedBy = { Include.IncludeValidator.class })
public @interface Include {
String message() default "{javax.validation.constraints.Include.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] value();
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List {
Include[] value();
}
/**
* 这个是自定义的校验逻辑
* 泛型中第一个是注解类名,第二个是参数的数据类型
*/
class IncludeValidator implements ConstraintValidator<Include, Integer> {
private Include constraintAnnotation;
@Override
public void initialize(Include constraintAnnotation) {
this.constraintAnnotation = constraintAnnotation;
}
@Override
public boolean isValid(Integer val, ConstraintValidatorContext constraintValidatorContext) {
boolean valid = false;
if (val != null) {
for (int i : this.constraintAnnotation.value()) {
if (i == val) {
valid = true;
break;
}
}
}
return valid;
}
}
}
2. 注解使用
将刚才新增的注解加在需要校验的字段上方
public class TestVO {
@Include(value = {1, 3}, message = "type只能等于1或者3")
private Integer type;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}
3. 启动验证
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class ValidateController {
@PostMapping("/test")
public String test(@RequestBody @Validated TestVO testVO) {
return "调用test接口成功";
}
public static void main(String[] args) {
SpringApplication.run(ValidateController.class, args);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
String handleException(MethodArgumentNotValidException e) {
return e.getBindingResult().getFieldError().getDefaultMessage();
}
}
4. 运行结果
这样自定义的扩展就完成了;