一、相关依赖
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
二、简单实例
添加一个普通的接口信息,限制传入的参数是 id不能小于 10。
@Validated
@RestController
@RequestMapping("/example")
public class ExampleController {
/**
* @param id id数不能小于10 @RequestParam类型的参数需要在Controller上增加@Validated
* @return
*/
@RequestMapping(value = "/info",method = RequestMethod.GET)
public String test(@Min(value = 10, message = "id最小只能是10") @RequestParam("id")
Integer id){
return "恭喜你拿到参数了";
}
}
在全局异常拦截中添加验证异常的处理
@Slf4j
@ControllerAdvice
@Component
public class GlobalExceptionHandler {
@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handle(ConstraintViolationException exception, HttpServletRequest request) {
Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
StringBuffer errorInfo = new StringBuffer();
for (ConstraintViolation<?> item : violations) {
/**打印验证不通过的信息*/
errorInfo.append(item.getMessage());
errorInfo.append(",");
}
log.error("{}接口参数验证失败,内容如下:{}",request.getRequestURI(),errorInfo.toString());
return "您的请求失败,参数验证失败,失败信息如下:"+ errorInfo.toString();
}
}
三、按照vo的验证
添加一个 vo 的实体信息
@Data
public class ExampleVo {
@NotBlank(message = "用户名不能为空")
private String userName;
@Range(min = 18,max = 60,message = "只能填报年龄在18~60岁的")
private String age;
}
添加一个 POST 请求的接口
/**
* @param vo 按照vo的验证
* @return
*/
@RequestMapping(value = "/info1",method = RequestMethod.POST)
public String test1(@Valid @RequestBody ExampleVo vo){
return "success";
}
在全局异常拦截中添加验证处理的结果
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public String handle(MethodArgumentNotValidException exception,HttpServletRequest request) {
StringBuffer errorInfo=new StringBuffer();
List<ObjectError> errors = exception.getBindingResult().getAllErrors();
for(int i=0;i<errors.size();i++){
errorInfo.append(errors.get(i).getDefaultMessage()+",");
}
log.error("{},接口参数验证失败:{}",request,errorInfo.toString());
return "您的请求失败,参数验证失败,失败信息如下:"+errorInfo.toString();
}
四、自定义注解
自定义注解实现,vo 中的属性必须符合枚举类中的枚举。
4.1 添加自定义注解
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumCheckValidator.class)
public @interface EnumCheck {
/**
* 是否必填 默认是必填的
* @return
*/
boolean required() default true;
/**
* 验证失败的消息
* @return
*/
String message() default "枚举的验证失败";
/**
* 分组的内容
* @return
*/
Class<?>[] groups() default {};
/**
* 错误验证的级别
* @return
*/
Class<? extends Payload>[] payload() default {};
/**
* 枚举的Class
* @return
*/
Class<? extends Enum<?>> enumClass();
/**
* 枚举中的验证方法
* @return
*/
String enumMethod() default "validation";
}
4.2 注解的校验逻辑实现类
public class EnumCheckValidator implements ConstraintValidator<EnumCheck,Object> {
private EnumCheck enumCheck;
@Override
public void initialize(EnumCheck enumCheck) {
this.enumCheck =enumCheck;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
// 注解表明为必选项 则不允许为空,否则可以为空
if (value == null) {
return this.enumCheck.required()?false:true;
}
//最终的返回结果
Boolean result=Boolean.FALSE;
// 获取 参数的数据类型
Class<?> valueClass = value.getClass();
try {
Method method = this.enumCheck.enumClass().getMethod(this.enumCheck.enumMethod(), valueClass);
result = (Boolean)method.invoke(this.enumCheck.enumClass(), value);
result= result == null ? false : result;
//所有异常需要在开发测试阶段发现完毕
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}finally {
return result;
}
}
}
4.3 枚举类
public enum Sex{
MAN("男",1),WOMAN("女",2);
private String label;
private Integer value;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
Sex(String label, int value) {
this.label = label;
this.value = value;
}
/**
* 判断值是否满足枚举中的value
* @param value
* @return
*/
public static boolean validation(Integer value){
for(Sex s:Sex.values()){
if(Objects.equals(s.getValue(),value)){
return true;
}
}
return false;
}
}
4.4 使用
@EnumCheck(message = "只能选男:1或女:2",enumClass = Sex.class)
private Integer sex;
五、分组验证
@Data
public class ExampleVo {
@NotNull(message = "主键不允许为空",groups = ValidGroupA.class)
private Integer id;
@NotBlank(message = "用户名不能为空",groups = Default.class)
private String userName;
@Range(min = 18,max = 60,message = "只能填报年龄在18~60岁的",groups = Default.class)
private String age;
@EnumCheck(message = "只能选男:1或女:2",enumClass = Sex.class,groups = Default.class)
private Integer sex;
}
@RequestMapping(value = "/info1",method = RequestMethod.POST)
public String test1(@Validated({ValidGroupA.class,Default.class}) @RequestBody ExampleVo vo) {
return "success";
}