谷粒商城实战笔记-69-商品服务-API-品牌管理-JSR303自定义校验注解


上一节讲解了如何使用分组校验。

这一节将详细介绍如何在Java中实现自定义校验注解以及配套的校验器。

1. 需求介绍

假设我们需要校验一个名为 showStatus 的字段,该字段只能接受 01 两个值。

为了实现这一需求,我们将创建一个自定义校验注解,并为其编写相应的校验器。

2. 创建自定义校验注解

创建自定义注解的步骤:

  • ① 创建注解类
  • ② 创建提示信息配置文件
  • ③ 创建校验器
  • ④ 管理注解类和校验器

2.1 编写自定义校验注解

2.1.1 注解定义

首先,我们需要定义一个自定义的校验注解 @ListValue,并为其提供必要的元数据。

在这里插入图片描述

ListValue注解类的代码如下。

package com.atguigu.common.validator.validate;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;


@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {

    String message() default "{com.xunqi.common.valid.ListValue.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    int[] vals() default { };

}

这段代码定义了一个自定义的校验注解 @ListValue,用于在Java应用程序中对特定的值进行校验。下面是这个注解的核心部分的解释:

  1. @Constraint(validatedBy = { ListValueConstraintValidator.class }):

    • 这个元注解表明 @ListValue 是一个校验注解,并指定了一个校验器 ListValueConstraintValidator。这个校验器负责具体的校验逻辑。
  2. public @interface ListValue:

    • 定义了一个名为 ListValue 的注解接口。
  3. String message() default "{com.xunqi.common.valid.ListValue.message}":

    • message 属性定义了当校验失败时的默认错误消息。这里的默认值是一个占位符,表示错误消息将从一个配置文件中读取,通常是在 ValidationMessages.properties 文件中。
  4. Class<?>[] groups() default {}:

    • groups 属性支持分组校验,允许用户定义不同的校验组,并且可以基于这些组选择性地执行校验。
  5. int[] vals() default {}:

    • vals 属性定义了允许的值列表。这是 @ListValue 注解特有的属性,用于指定哪些整数值是合法的。

@ListValue 注解被设计用来校验一个字段或参数的值是否在一个预定义的整数列表中。

使用这个注解将调用 ListValueConstraintValidator 来验证值是否有效。

如果校验失败,则会抛出一个包含错误消息的异常,错误消息从配置文件中获取。

2.1.2 配置文件

我们还需要创建一个配置文件来定义错误消息。

# ValidationMessages.properties
com.example.validation.ListValue.message=必须提交指定的值

在这里插入图片描述

3. 实现自定义校验器

3.1 编写自定义校验器

为了执行具体的校验逻辑,我们需要实现 ConstraintValidator 接口。

package com.atguigu.common.validator.validate;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;


public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

    private Set<Integer> set = new HashSet<>();

    /**
     * 初始化方法
     * @param constraintAnnotation
     */
    @Override
    public void initialize(ListValue constraintAnnotation) {

        int[] vals = constraintAnnotation.vals();

        for (int val : vals) {
            set.add(val);
        }

    }

    /**
     * 判断是否效验成功
     * @param value 需要效验的值
     * @param context
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {

        //判断是否有包含的值
        boolean contains = set.contains(value);

        return contains;
    }

}

  • initialize: 在校验开始前初始化校验器,获取允许的值列表。
  • isValid: 校验逻辑,检查给定值是否在允许的值列表中。

4. 使用自定义校验

在实体类中,我们可以使用 @ListValue 注解标记需要校验的字段。

public class BrandEntity {
    // ...
    @ListValue(values = {0, 1})
    private Integer showStatus;
    // ...
}

5. 多类型校验器的支持

如果 showStatus 字段的类型改变,例如变为 Double,我们可能需要额外的校验器来处理这种类型。在这种情况下,我们可以通过在 @ListValue 注解中指定多个校验器来解决这个问题。

@Constraint(validatedBy = {ListValueValidatorForInteger.class, ListValueValidatorForDouble.class})
public @interface ListValue {
    // ...
}

6. 测试

最后,我们需要确保前后端都实现了数据校验,并且能够正确处理各种情况,如分组校验和自定义校验。

  • 前端校验:确保前端能够识别错误并给出提示。
  • 后端校验:确保后端能够正确识别和处理不符合要求的数据。

在这里插入图片描述

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值