自定义注解-动态传入允许的值

希望在校验时动态指定允许的值(例如 0 和 1),而不是硬编码在注解中,可以通过 ​​自定义注解 + 动态参数​​ 的方式实现。

​解决方案:自定义注解 @InValues,支持动态传入允许的值​​

我们可以定义一个注解 @InValues,允许传入一个 int[] 数组,校验参数是否在指定的值范围内。

​1. 定义 @InValues 注解​​

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = InValuesValidator.class) // 指定校验器
public @interface InValues {
    String message() default "值不在允许范围内";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    
    // 允许的值数组
    int[] values();
}

​​2. 实现校验逻辑 InValuesValidator​​

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class InValuesValidator implements ConstraintValidator<InValues, Integer> {
    private int[] allowedValues;

    @Override
    public void initialize(InValues constraintAnnotation) {
        this.allowedValues = constraintAnnotation.values(); // 初始化允许的值
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value == null) {
            return true; // 如果允许 null,可以返回 true;否则返回 false
        }
        for (int allowedValue : allowedValues) {
            if (value == allowedValue) {
                return true;
            }
        }
        return false;
    }
}

​3. 在实体类中使用 @InValues​​

public class MyRequest {
    @InValues(values = {0, 1}, message = "值必须是 0 或 1")
    private Integer status;

    // getter & setter
}

​​4. 在 Controller 中使用 @Validated 校验​​

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated
public class MyController {
    @PostMapping("/validate")
    public String validate(@RequestBody @Validated MyRequest request) {
        return "Valid";
    }
}

​5. 测试​​

  • ​​✅ 合法请求​​(status=0 或 status=1):
{"status": 0}  // 通过
{"status": 1}  // 通过
  • ❌ 非法请求​​(status=2):
    {"status": 2}  // 返回 400 Bad Request,错误信息:"值必须是 0 或 1"

6. ​​进阶:支持动态传值

适用于方法参数校验

如果希望在校验时动态传入允许的值(而不是硬编码在注解中),可以使用 ​​@interface + @Constraint + @Target + @Retention​​ 结合 ​​@Validated​​ 实现。
​​示例:动态校验方法参数​​

import org.springframework.validation.annotation.Validated;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DynamicInValuesValidator.class)
public @interface DynamicInValues {
    String message() default "值不在允许范围内";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    // 使用 String 数组存储允许的值(避免编译时硬编码)
    String[] values() default {};
}

但由于 @interface 的 values() 是编译时常量,无法动态传值,因此 ​​Spring Validation 不支持直接在方法参数上动态校验​​。

​​替代方案​​:

  • ​​使用 @Validated + 自定义校验逻辑​​(在 Service 层手动校验)。
  • ​​使用 @Pattern + 字符串转换​​(适用于简单场景)。

7. ​​总结​​

方案适用场景是否支持动态传值备注
​​@InValues(推荐)​​校验 Integer 是否在指定范围内❌ 硬编码在注解中最常用
​​@Pattern + 字符串转换​​简单校验❌ 不推荐需要额外转换
​​@AssertTrue​​对象校验❌ 不推荐需要额外方法
​​动态校验(Service 层)​​动态传值✅ 支持需手动校验

​​推荐使用 @InValues 注解​​,代码清晰且可复用。如果需要动态传值,建议在 ​​Service 层手动校验​​。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值