这里写自定义目录标题
validator的使用
在日常工作中,经常要对各种参数进行校验,代码中总是包含着各种if-else校验,导致代码相当冗长,而且稍不注意很容易踩坑。如何利用spring的javax.validation注解,高效写出简洁的代码,今天就是我们要讨论的话题。
为什么要用validator
- javax.validation注解可以帮我们完成很多参数校验,免去繁琐的串行校验
- 可用于各种项目程序中,不限于spring框架
- 基于JSR-303标准验证规范接口,方便扩展与升级
注解:
- JSR:Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
- JSR-303:是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
Bean Validation 中内置的 constraint

validator如何使用
由于Bean Validation只是提供基本的功能,在现实中,我们会遇到各种校验的需求,显然Bean Validation并不能很好符合我们的需要,因此本文将以Hibernate Validator作为实践案例做介绍,另外,由于我们只是讨论validator的使用,所以为了构建方便,我们使用spring-boot作为构建应用的基础框架。
注解:Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。

Hibernate Validator注解
可查看org.hibernate.validator.constraints包路径下支持哪些注解
Hibernate Validator引入
由于使用spring-boot-starter-web,已经集合了hibernate-validator:6.0.13.Final和validation-api:2.0.1.Final,所以我们不需要阴引入,如果不是使用spring-boot,则需要自行引入。
<!--jsr 303-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
业务编写
- controller编写
@RequestMapping("/user/save")
public BaseDto save(@Validated UserSaveRequest data) {
return BaseDto.success();
}
- bean的编写
public class BaseDto<T> {
public BaseDto() {
}
public BaseDto(int code, String msg) {
this.code = code;
this.msg = msg;
}
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static BaseDto success() {
BaseDto data = new BaseDto();
data.setCode(200);
data.setMsg("OK");
return data;
}
}
public class UserSaveRequest {
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
private String mobile;
}
- 验证异常代码统一处理
@RestControllerAdvice
public class GlobalExceptionController {
@ExceptionHandler(BindException.class)
public BaseDto handleMValidException(BindException e) {
return BaseDto.fail(102, e.getBindingResult().getFieldError().getDefaultMessage());
}
}
- 测试
{
"code": 102,
"msg": "联系邮箱不能为空"
}
自定义标签
添加手机号校验
- 添加注解
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
public @interface PhoneNumber {
String message() default "手机号不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
备注:
- message 定制化的提示信息,主要是从ValidationMessages.properties里提取,也可以依据实际情况进行定制
- groups 这里主要进行将validator进行分类,不同的类group中会执行不同的validator操作
- payload 主要是针对bean的,使用不多。
- 添加验证规则
public class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, Object> {
public void initialize(PhoneNumber identityCardNumber) {
}
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
if (o == null) {
return false;
}
String data = o.toString();
Matcher m = Pattern.compile("^[1][3,4,5,6,7,8,9][0-9]{9}$").matcher(data);
return m.find();
}
}
- 对bean添加注解
public class UserSaveRequest {
@NotBlank(message = "手机号不能为空")
@PhoneNumber(message = "手机号有误")
private String mobile;
}
使用groups的校验
场景:如果我们需要在插入的时候不校验手机号,但是在修改的时候要校验手机号,这时候就需要用上groups了
- 定义分组接口
public interface Create extends Default {
}
public interface Update extends Default {
}
- controller入参的改写
@RequestMapping("/user/save")
public BaseDto save(@Validated(Update.class) UserSaveRequest data) {
return BaseDto.success();
}
@RequestMapping("/user/create")
public BaseDto Create(@Validated(Create.class) UserSaveRequest data) {
return BaseDto.success();
}
- bean的改写
@NotBlank(message = "手机号不能为空", groups = Update.class)
@PhoneNumber(message = "手机号有误", groups = Update.class)
private String mobile;
最后,将会达到我们预期的结果
本文探讨如何利用Spring框架中的javax.validation注解,通过HibernateValidator简化参数校验过程,实现代码的高效与简洁。同时,介绍了自定义校验标签及groups分组校验的实践方法。
1251

被折叠的 条评论
为什么被折叠?



