1.引入依赖,版本需要对应:其中javax.validation是定义规范的一些接口,而实现由hibernate-validator实现
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.7.Final</version> </dependency>
2.创建一个请求对象:
public class OrderRequest { private Long id; @NotBlank(message ="名称不能为空" ) private String name; @Pattern(regexp = "http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?",message = "url路径不对") private String url; @Email(regexp="/+d/",message = "邮件格式不对") private String email; @DecimalMax("20") @DecimalMin("10") private BigDecimal amount; }
3.contoller实现:
@RequestMapping("/order")
@ResponseBody
public Map<String, String> testValid(@Valid @RequestBody OrderRequest orderRequest, BindingResult bindingResult){
boolean hasFieldErrors = bindingResult.hasFieldErrors();
Map<String, String> map = new HashMap<>();
if(hasFieldErrors){
for (FieldError fieldError : bindingResult.getFieldErrors()) {
String field = fieldError.getField();
String defaultMessage = fieldError.getDefaultMessage();
map.put(field,defaultMessage);
}
map.put("errorCode","400");
return map;
}
map.put("errorCode","200");
return map;
}
4.postman调用:

问题1:当所给的注解都满足不了需求的时候,如何自定义注解:需求:校验姓名是否带有gogo,参考注解:


参考上面NotBlank注解,定义一个Checkgogo注解:
@Documented @Constraint(validatedBy = { }) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) public @interface CheckGogo { String message() default "{com.yang.xiao.hui.thymeleaf.controller.CheckGogo.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; String value(); }
我们需要定义一个使得该注解生效的类,点击@Constraint注解,看看需要一个怎么样的类:


实现如下:
public class MyGogoConstraintValidator implements ConstraintValidator<CheckGogo,String> { private String needIncludeValue; @Override public void initialize(CheckGogo constraintAnnotation) { needIncludeValue = constraintAnnotation.value(); //参数需要包含的字符 } @Override public boolean isValid(String value, ConstraintValidatorContext context) { return value.indexOf(needIncludeValue)!=-1 //校验参数是否包含该字符 } }
在注解上加上该实现类:

配置默认信息:在resources文件夹下新增:ValidationMessages.properties

测试:

postMan调用:

自定义提示语:


问题2:有些字段,我们在修改时希望不为空,在新增时希望为空,如编号,如何处理? 这里就要用到分组了,先定义2个空接口:
//新增分组 public interface AddCheck { } //修改分组 public interface UpdateCheck { }
在校验字段时加上分组字段:

修改controller:

测试:

问题3:上面所讲,校验失败后,每个controller都要自己处理校验失败的异常,如何统一校验:
定义一个异常处理类:
@RestControllerAdvice(basePackages="com.yang.xiao.hui.thymeleaf.controller") public class CommonExceptionProcessController { @ExceptionHandler(value = MethodArgumentNotValidException.class) public Map errorHandler(MethodArgumentNotValidException ex) { //处理参数校验异常 Map map = new HashMap(); BindingResult bindingResult = ex.getBindingResult(); for (FieldError fieldError : bindingResult.getFieldErrors()) { map.put(fieldError.getField(), fieldError.getDefaultMessage()); } map.put("code", 400); return map; } @ExceptionHandler(value = Throwable.class) public Map errorHandler(Throwable ex) { Map map = new HashMap(); map.put("code", 500); map.put("message", "服务挂了"); return map; } }
修改controller:
@RequestMapping("/order")
@ResponseBody
public BigDecimal testValid(@Validated(UpdateCheck.class) @RequestBody OrderRequest orderRequest){ //这里不用再单独处理bindResult了,只管业务代码即可
return new BigDecimal("20");
}
postMan调用:
