Validation框架的应用

如果之后需要的话,会再开博客描写,这样会显得主题突出一些。

后续扩展部分会解释message,groups,payload三个核心属性等。

自定义注解部分,会给出蚂蚁金服内部真实采用的自定义校验注解。

二,简介

简单来说,就是通过Validation框架,进行数据的各类校验。从Java的基本数据类型到自定义封装数据类型,从非空判断到正则表达式判断,都是Validation框架所支持的。

在Validation之前,层次架构中,开发者总是采用分层验证模型。就是分别在控制层,服务层,数据层等分别对目标对象的目标属性进行校验。很明显,这是非常不优雅的,而且开发效率低,因为存在大量重复校验逻辑。

而Validation则提出一个元数据验证模型,而在Spring体系中,则表现为Java Bean验证模型。站在Spring角度来说,无论是在哪个层次,都是针对Java Bean进行验证的。所以,Validation则通过在目标Bean上添加约束注解,以及背后的验证程序,实现了一个对业务代码无侵入的校验功能。

三,使用方法 1.添加依赖 <!-- Validation 相关依赖 --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency>

这是Validation框架的核心依赖。

该依赖是包含在SpringBoot的spring-boot-web-starter中的。所以如果使用了前面Spring-boot-web-starter依赖,则不需要再次引入Validation框架的依赖。

至于EL等依赖,常用于自定义注解,具体可以根据需要进行依赖引入。

2.添加约束注解

针对目标Bean,针对不同属性的验证需求,添加不同的约束注解。

如UserVo的userId,添加@NotNull注解,表示这个属性在验证框架中不可为空。

有关约束注解,后面有详尽描述。

3.开启验证

即使对元数据模型添加了约束注解,但是还没有明确开启验证流程。站在Validation框架的角度,它并不知道应该在什么时候进行校验。因为除了控制层,我们还可能在服务层验证。即使是在服务层,一个调用链路,可能涉及多个方法,也需要确定在哪个方法进行验证。

那么,开启验证的方法有两种(也许还有别的方法,欢迎补充):

验证注解:@Validated或者@Valid

初始化验证器:Validation.buildDefaultValidatorFactory().getValidator();

验证注解

@Validated注解的效果与@Valid是一样的,毕竟@Validated是SpringBoot对@Valid注解的封装(@Valid是Java的自带的注解)。而@Validated注解是包含在SpringBoot的spring-boot-web-starter中的。

在对应位置添加@Validated注解(当程序执行到这里,就会执行对应的校验逻辑):

自定义对象(启动注解在自定义对象前) @PostMapping("save.do") @ResponseBody public ServerResponse saveConfig(@Validated(InclinationConfig.ConfigCommitGroup.class) InclinationConfig inclinationConfig) { // 业务逻辑 } 基本数据类型() @Validated public class demo { @PostMapping("get.do") @ResponseBody public ServerResponse getConfig(int configId) { // 业务逻辑 } }

针对Java基本数据类型的@NotNull,则需要将对应类上添加@Validated注解。

验证器

初始化,建立验证器对象(Validator对象):

// 验证器对象 private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

获取验证结果集合(这里也就是开启验证的时间位置):

// 验证结果集合 private Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo); // 验证过程可以添加分组信息 private Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo,UserInfo.RegisterGroup.class);

处理验证结果集合:

set.forEach(item -> { // 输出验证错误信息 System.out.println(item.getMessage()); });

当然啦。更多情况下,我们是直接抛出异常的:

// 判断验证结果集是否为空(验证结果集放的都是验证失败时的message) if(!CollectionUtils.isEmpty(set)) { // 循环时,采用StringBuilder可以有效提高效率(详见String,StringBuilder,StringBuffer三者区别) StringBuilder exceptionMessage = new StringBuilder(); set.forEach(validationItem -> { exceptionMessage.append(validationItem.getMessage()); }); // 直接抛出异常(其实这也就是@Valid注解的默认校验器的做法) throw new Exception(exceptionMessage.toStrring()); } 四,约束注解 1.初级应用:常用注解

这里给出了Validation框架(validation-api-2.0.1.Final)中constraints下全部的注解说明:

空值校验:

@Null:目标值为null。比如,注册时的userId当然是null(即使不为null,系统也不会采用的)。

@NotNull:目标值不为null。比如,登录时的userId当然不为null(当然也可能是通过了外部鉴权,然后内部裸奔)。

@NotEmpty:目标值不为empty。相较于上者,增加了对空值的判断(就是""无法通过@NotEmpty的校验)

@NotBlank:目标值不为blank。相较于上者,增加了对空格的判断(就是空格无法通过@NotBlank校验的)

范围校验:

@Min:针对数值类型,目标值不能低于该注解设定的值。

@Max:针对数值类型,目标值不能高于该注解设定的值。

@Size:针对集合类型,目标集合的元素数量不可以高于max参数,不可以低于min参数。

@Digits:针对数值类型,目标值的整数位数必须等于integer参数设定的值,小数位数必须等于fraction参数设定的值。

@DecimalMax:针对数值类型,目标值必须小于该注解设定的值。

@DecimalMin:针对数值类型,目标值必须大于该注解设定的值。

@Past:针对于日期类型,目标值必须是一个过去的时间。

@PastOrPresent:针对于日期类型,目标值必须是一个过去或现在的时间。

@Future:针对于日期类型,目标值必须是未来的时间。

@FutureOrPresent:针对于日期类型,目标值必须是未来或未来的时间。

@Negative:针对数值类型,目标值必须是负数。

NegativeOrZero:针对数值类型,目标值必须是非正数。

@Positive:针对数值类型,目标值必须是正数。

@PositiveOrZero:针对数值类型,目标值必须是非负数。

其他校验:

@AssertTrue:针对布尔类型,目标值必须为true。

@AssertFalse:针对布尔类型,目标值必须为false。

@Email:针对字符串类型,目标值必须是Email格式。

@URL:针对字符串类型,目标值必须是URL格式。

@Pattern:针对字符串类型,目标值必须通过注解设定的正则表达式。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzxxy.html