boot 版本:2.4.4 本章节参考博客
# 引入依赖
# 该依赖中有一个 hibernate-validator 的包:org.hibernate:hibernate-validator
implementation 'org.springframework.boot:spring-boot-starter-web'
构建需要校验的实体类
public class Foo {
@NotBlank
private 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;
@Controller
public 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
@RestControllerAdvice
public 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;
/// BindException
if (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;
// 直接注入这个校验器对象
@Autowired
private 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();
}