使用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,不能为空
posted @   漠孤烟  阅读(716)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示