You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中@Max、@Min、@Valid注解的工作原理及自定义实现问询

Java校验注解(@Valid/@Max)工作机制与自定义实现

一、@Valid/@Max等注解的工作机制

Java参数校验基于**JSR-380(Bean Validation 2.0)**规范,Hibernate Validator是它的主流实现,Spring框架也深度集成了这套机制,核心流程如下:

  1. 约束标记与触发

    • @Max、@Min这类注解是约束注解,仅标记字段需遵循的规则(比如@Max(value=100)表示字段值不能超过100),本身不包含校验逻辑。
    • @Valid是校验触发开关:在Controller方法参数、嵌套对象上标记@Valid时,Spring会启动校验流程。
  2. 校验器初始化

    • 应用启动时,Bean Validation会扫描所有带@Constraint注解的类,为每个约束注解绑定对应的ConstraintValidator实现类(比如@Max对应MaxValidator)。
    • 这些Validator会被加载到ValidatorFactory中,供后续校验调用。
  3. 校验执行流程

    • 请求到达Controller后,Spring发现参数带@Valid,会从ValidatorFactory获取Validator实例。
    • Validator遍历目标对象的字段,识别约束注解,找到对应的ConstraintValidator,调用其isValid()方法执行校验。
    • 若字段值不符合约束,会生成错误信息,最终封装到BindingResult或抛出MethodArgumentNotValidException。

二、自定义类似@Max的校验注解(以@MyMax为例)

自定义约束注解只需两步:定义注解、实现校验逻辑,具体如下:

1. 定义约束注解@MyMax

通过@Constraint指定对应的校验器,同时定义必要属性(最大值、错误提示等):

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

@Documented
@Constraint(validatedBy = MyMaxValidator.class) // 绑定校验器
@Target({ElementType.FIELD, ElementType.PARAMETER}) // 可用于字段和方法参数
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
public @interface MyMax {
    // 默认错误提示
    String message() default "值不能超过指定最大值";

    // 分组校验用,默认空数组
    Class<?>[] groups() default {};

    // 负载信息,用于传递额外数据,默认空数组
    Class<? extends Payload>[] payload() default {};

    // 核心属性:最大值
    long value();
}

2. 实现ConstraintValidator校验逻辑

编写MyMaxValidator类,实现ConstraintValidator接口,重写初始化和校验方法:

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

public class MyMaxValidator implements ConstraintValidator<MyMax, Number> {
    private long maxValue;

    // 初始化:获取注解上的最大值配置
    @Override
    public void initialize(MyMax constraintAnnotation) {
        this.maxValue = constraintAnnotation.value();
    }

    // 核心校验逻辑:判断值是否符合规则
    @Override
    public boolean isValid(Number value, ConstraintValidatorContext context) {
        // 允许值为null(如需强制非null,需配合@NotNull注解)
        if (value == null) {
            return true;
        }
        // 针对不同数值类型做比较
        if (value instanceof Integer) {
            return value.intValue() <= maxValue;
        } else if (value instanceof Long) {
            return value.longValue() <= maxValue;
        } else if (value instanceof Double) {
            return value.doubleValue() <= maxValue;
        }
        // 其他数值类型可自行扩展
        return false;
    }
}

3. 使用自定义注解

在实体类或方法参数上使用@MyMax,搭配@Valid触发校验:

// 实体类示例
public class User {
    @MyMax(value = 100, message = "年龄不能超过100岁")
    private Integer age;

    // getter/setter 省略
}

// Controller示例
@RestController
public class UserController {
    @PostMapping("/users")
    public String addUser(@Valid @RequestBody User user) {
        // 校验通过才会执行到此处
        return "用户创建成功";
    }
}

4. 触发校验

调用/users接口传入age=101时,Spring会触发MyMaxValidator的校验,抛出MethodArgumentNotValidException,返回包含错误信息的响应。


内容的提问来源于stack exchange,提问作者juni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:25:14