使用jakarta.validation自定义校验规则
jakarta.validation
是一套数据校验的规范
依赖包为:
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
这是一个接口规范包,不包含实现。实现jakarta.validation规范的框架有hibernate-validator
,只需要pom.xml里引入该依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.1.Final</version>
</dependency>
但代码里无任何hibernate-validator的import依赖,想切换到其他家的实现时,只需pom.xml里改一下,
代码可以不用任何修改,这也是Jakarta EE的一向主张:面象接口编程,依赖包也是如此,接口包和实现包分离,业务代码只依赖接口包,不依赖具体实现包。
由于message里可以进行表达式,还需要jakarta.el及其实现
示例
jakarta.validation
内置了NotBlank
, NotNull
, Min
, Pattern
等校验注解外,还提供了自定义注解进行任意校验规则的扩展,其接口类为ConstraintValidator
,只需要对该接口进行自定义实现,即可定义出自己想要的校验注解。
下面使用注解来校验值是否为一个合格的cron表达式。
1、创建annotation
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IsCronExpression {
String message() default "表达式格式错误";
//分组校验
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2、创建对应的校验器
public class IsCronExpressionValidator implements ConstraintValidator<IsCronExpression, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
try {
CronExpression.parse(value);
return true;
} catch (Exception e) {
return false;
}
}
}
3、在IsCronExpression 上指定校验器
@Constraint(validatedBy = {IsCronExpressionValidator.class})
4、使用 @IsCronExpression
@Data
public class TaskRequest {
@NotBlank
private String taskName;
@NotBlank
private String description;
/**
* 表达式
*/
@NotBlank
@IsCronExpression
private String taskCron;
}
5、单元测试
@Test
void validDataObject() {
TaskRequest taskRequest = new TaskRequest();
taskRequest.setTaskName(null);
taskRequest.setTaskCron("61 */3 * * * ?");
taskRequest.setDescription("描述");
try (ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();) {
Set<ConstraintViolation<TaskRequest>> result = validatorFactory.getValidator().validate(taskRequest);
result.forEach(violation -> {
String message = "字段:%s,值:%s,%s"
.formatted(violation.getPropertyPath(), violation.getInvalidValue(), violation.getMessage());
System.out.println(message);
});
}
}
输出:
字段:taskCron,值:61 */3 * * * ?,表达式格式错误
字段:taskName,值:null,不能为空
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步