boot 版本:2.4.4 本章节参考博客
# 引入依赖# 该依赖中有一个 hibernate-validator 的包:org.hibernate:hibernate-validatorimplementation 'org.springframework.boot:spring-boot-starter-web'
构建需要校验的实体类
public class Foo {@NotBlankprivate String name;@Min(18)private Integer age;@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")@NotBlank(message = "手机号码不能为空")private String phone;@Email(message = "邮箱格式错误")private String email;//... getter setter
框架提供的校验注解
JSR提供的校验注解:@Null 被注释的元素必须为 null@NotNull 被注释的元素必须不为 null@AssertTrue 被注释的元素必须为 true@AssertFalse 被注释的元素必须为 false@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max=, min=) 被注释的元素的大小必须在指定的范围内@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内@Past 被注释的元素必须是一个过去的日期@Future 被注释的元素必须是一个将来的日期@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式Hibernate Validator提供的校验注解:@NotBlank(message =) 验证字符串非null,且长度必须大于0@Email 被注释的元素必须是电子邮箱地址@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内@NotEmpty 被注释的字符串的必须非空
在 @Controller 中校验
方式 1:在方法中自己获取到校验结果,自己处理后返回
import org.springframework.validation.annotation.Validated;import org.springframework.validation.BindingResult;@Controllerpublic class FooController {@RequestMapping("/foo")public String foo(@Validated Foo foo, BindingResult bindingResult) {// 判断是否有错误if(bindingResult.hasErrors()){// 获取到每个字段的错误信息for (FieldError fieldError : bindingResult.getFieldErrors()) {//...}return "fail";}return "success";}}
方式 2:利用全局处理器来实现
import org.springframework.validation.BindException;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseStatus;import org.springframework.web.bind.annotation.RestControllerAdvice;@Slf4j@RestControllerAdvicepublic class GlobalExceptionHandler {/*** 处理Validated校验异常* <p>* 注: 常见的 ConstraintViolationException 异常, 也属于 ValidationException 异常** @param e 捕获到的异常* @return 返回给前端的 data*/@ResponseStatus(code = HttpStatus.BAD_REQUEST)@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})public Result handleParameterVerificationException(Exception e) {String msg = null;/// BindExceptionif (e instanceof MethodArgumentNotValidException) {BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();// getFieldError 获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)FieldError fieldError = bindingResult.getFieldError();if (fieldError != null) {msg = fieldError.getField() + " " + fieldError.getDefaultMessage();}/// ValidationException 的子类异常 ConstraintViolationException} else if (e instanceof BindException) {// getFieldError 获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)FieldError fieldError = ((BindException) e).getFieldError();if (fieldError != null) {msg = fieldError.getField() + " " + fieldError.getDefaultMessage();}/// MethodArgumentNotValidException} else if (e instanceof ConstraintViolationException) {/** ConstraintViolationException 的 e.getMessage() 形如* {方法名}.{参数名}: {message}* 这里只需要取后面的 message 即可*/msg = e.getMessage();if (msg != null) {int lastIndex = msg.lastIndexOf(':');if (lastIndex >= 0) {msg = msg.substring(lastIndex + 1).trim();}}/// ValidationException 的其它子类异常} else {msg = "处理参数时异常: 参数校验未识别的异常类型";log.error(" 参数校验未识别的异常类型", e);}// 你自己封装的 result 类return ResultHelper.badRequest(msg);}}
手动调用方式校验
方式 1:使用 Hibernate Validation API
Foo foo = new Foo();foo.setAge(22);foo.setEmail("000");// 通过这种方式获取到校验器ValidatorFactory vf = Validation.buildDefaultValidatorFactory();Validator validator = vf.getValidator();Set<ConstraintViolation<Foo>> set = validator.validate(foo);for (ConstraintViolation<Foo> constraintViolation : set) {System.out.println(constraintViolation.getMessage());}
方式 2:使用 Spring 封装之后的校验器
import javax.validation.ConstraintViolation;import javax.validation.Validator;// 直接注入这个校验器对象@Autowiredprivate Validator globalValidator;final Set<ConstraintViolation<Foo>> errors = globalValidator.validate(foo);for (ConstraintViolation<Foo> constraintViolation : errors) {// 拿到错误的字段final String field = constraintViolation.getPropertyPath().toString();// 拿到错误的信息String error = constraintViolation.getMessage();}
