导读:本期聚焦于小伙伴创作的《Lombok类中如何实现至少一个字段必须存在的校验》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Lombok类中如何实现至少一个字段必须存在的校验》有用,将其分享出去将是对创作者最好的鼓励。

在Java项目开发中,Lombok通过注解简化了实体类的getter、setter、构造方法等模板代码的编写,但默认的Lombok注解无法支持“至少一个字段必须存在”这类自定义校验规则。这类需求在业务场景中非常常见,比如用户注册时,手机号、邮箱、第三方账号标识至少要提供一个,否则不允许提交数据。

Lombok类中如何实现至少一个字段必须存在的校验

基于JSR303自定义校验注解实现

JSR303是Java的校验规范,我们可以自定义一个校验注解,配合校验器实现至少一个字段非空的逻辑,这种方式可以和Spring的校验体系无缝集成,适合Web项目使用。

1. 定义自定义校验注解

首先创建@AtLeastOneNotNull注解,指定需要校验的字段组:

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

@Documented
@Constraint(validatedBy = AtLeastOneNotNullValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AtLeastOneNotNull {
    // 需要校验的字段名称数组
    String[] fieldNames();
    // 校验失败后的提示信息
    String message() default "至少一个字段不能为空";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

2. 实现校验器逻辑

创建对应的校验器,通过反射获取指定字段的值,判断是否至少有一个不为空:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;

public class AtLeastOneNotNullValidator implements ConstraintValidator<AtLeastOneNotNull, Object> {
    private String[] fieldNames;

    @Override
    public void initialize(AtLeastOneNotNull constraintAnnotation) {
        this.fieldNames = constraintAnnotation.fieldNames();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        try {
            for (String fieldName : fieldNames) {
                Field field = value.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Object fieldValue = field.get(value);
                // 判断字段值不为空
                if (fieldValue != null && !"".equals(fieldValue.toString().trim())) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }
}

3. 在Lombok类中使用注解

在Lombok标注的实体类上添加自定义注解,指定需要校验的字段:

import lombok.Data;
import javax.validation.constraints.NotNull;

@Data
@AtLeastOneNotNull(fieldNames = {"phone", "email", "idCard"}, message = "手机号、邮箱、身份证号至少要提供一个")
public class UserRegisterDTO {
    private String phone;
    private String email;
    private String idCard;
    private String username;
}

在Spring接口中使用@Valid注解触发校验,校验失败会抛出MethodArgumentNotValidException异常,可统一捕获处理。

在Lombok构造方法中添加校验逻辑

如果项目没有引入校验框架,也可以利用Lombok的@AllArgsConstructor或者自定义构造方法,在构造对象时执行校验逻辑。

1. 使用@Builder配合自定义构造方法

Lombok的@Builder可以生成建造者模式代码,我们可以在建造者的build方法中添加校验:

import lombok.Builder;
import lombok.Getter;

@Getter
public class ContactInfo {
    private final String phone;
    private final String email;
    private final String address;

    @Builder
    private ContactInfo(String phone, String email, String address) {
        // 校验至少一个字段不为空
        if (phone == null && email == null && address == null) {
            throw new IllegalArgumentException("手机号、邮箱、地址至少要提供一个");
        }
        this.phone = phone;
        this.email = email;
        this.address = address;
    }

    // 自定义建造者,暴露静态方法创建建造者
    public static ContactInfoBuilder builder() {
        return new ContactInfoBuilder();
    }

    // 内部建造者类,重写build方法
    public static class ContactInfoBuilder {
        private String phone;
        private String email;
        private String address;

        ContactInfoBuilder() {
        }

        public ContactInfoBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public ContactInfoBuilder email(String email) {
            this.email = email;
            return this;
        }

        public ContactInfoBuilder address(String address) {
            this.address = address;
            return this;
        }

        public ContactInfo build() {
            return new ContactInfo(this.phone, this.email, this.address);
        }

        @Override
        public String toString() {
            return "ContactInfoBuilder{" +
                    "phone='" + phone + ''' +
                    ", email='" + email + ''' +
                    ", address='" + address + ''' +
                    '}';
        }
    }
}

使用示例:

public class Test {
    public static void main(String[] args) {
        // 正常创建对象
        ContactInfo info1 = ContactInfo.builder()
                .phone("13800138000")
                .build();
        // 校验失败会抛出异常
        try {
            ContactInfo info2 = ContactInfo.builder().build();
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}

两种方案对比

方案优点缺点适用场景
自定义JSR303注解和Spring校验体系集成好,支持统一异常处理,注解复用性高需要引入校验依赖,实现步骤稍多Spring Boot Web项目,需要统一参数校验的场景
构造方法/Builder校验无额外依赖,逻辑直观,编译期就能发现问题校验逻辑和类强耦合,复用性低,不支持自动校验触发非Web项目,或者校验逻辑仅在该类使用的场景

注意事项

  • 自定义JSR303校验器中使用反射获取字段时,要注意字段的访问权限,私有字段需要调用setAccessible(true)
  • 如果字段是基础类型(如int、boolean),默认值不为null,需要额外判断默认值是否符合业务要求
  • Lombok的@Data注解会生成所有字段的getter和setter,如果校验逻辑放在setter中,要注意避免无限递归的问题

Lombok字段校验Java_Bean自定义注解validation修改时间:2026-07-20 15:48:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。