JSR 303 - Bean Validation
在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情。应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的。
在通常的情况下,应用程序是分层的,不同的层由不同的开发人员来完成。
很多时候同样的数据验证逻辑会出现在不同的层,这样就会导致代码冗余和一些管理的问题,比如说语义的一致性等。
为了避免这样的情况发生,最好是将验证逻辑与相应的域模型进行绑定。
于是 JSR 303 - Bean Validation
应运而生。
在Maven中使用
在Maven的pom.xml
中引入validation-api
javax.validation
validation-api
2.0.1.Final
复制代码
validation-api
的一个很好的补充来源于hibernate
,虽然hibernate
已经远去,但是其留存下来了很多精髓。
org.hibernate.validator
hibernate-validator
复制代码
注解列表
Bean Validation 中内置的 constraint
@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(value) 被注释的元素必须符合指定的正则表达式
复制代码
Hibernate Validator 附加的 constraint
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内
复制代码
自定义注解
通过实现ConstraintValidator
可以自定义参数注解。
Mobile.java
@Target( {
METHOD,
FIELD,
ANNOTATION_TYPE,
CONSTRUCTOR,
PARAMETER
})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MobileValidator.class})
public @interface Mobile {
String regexp() default "";
String message() default "手机号码格式不正确";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
复制代码
MobileValidator.java
public class MobileValidator implements ConstraintValidator<Mobile, String> {
/**
* 手机号的正则表达式.
*/
private static Pattern pattern = Pattern.compile(
"^0?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$");
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
Matcher m = pattern.matcher(value);
return m.matches();
}
@Override
public void initialize(Mobile constraintAnnotation) {}
}
复制代码
如此,我们就可以在Bean中使用注解@Mobile
了。
User.java
@Data
public class User {
@NotBlank
private String userName;
@Mobile
private String mobile;
}
复制代码
Spring Boot 中使用
方法级别的校验配置
@Configuration
public class ValidateConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(){
return new MethodValidationPostProcessor();
}
}
复制代码
1. 使用@Valid
进行参数校验
@RequestMapping(value = "/book", method = RequestMethod.POST)
public void addBook(@RequestBody @Valid Book book) {
System.out.println(book.toString());
}
复制代码
2. 在类上使用@Validated
进行参数校验
@RestController
@Validated
public class ValidateController {
// ...
}
复制代码
异常拦截
针对参数异常BindException
进行全局异常拦截。
GlobalWebExceptionHandler.java
@ControllerAdvice
public class GlobalWebExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalWebExceptionHandler.class);
/**
* 定义参数异常处理器.
*
* @param e 当前平台异常参数对象.
* @return org.springframework.http.ResponseEntity
*/
@ExceptionHandler(BindException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity