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

如何不使用@Valid注解,通过模型字段注解验证NotifyUser实例?

问题与解决方案

问题说明

接收包含手机号的文件,处理后存入数据库。目前仅能在方法参数上使用@Valid注解,但希望复用NotifyUser模型字段上的验证注解完成手机号校验,避免手动编写重复的验证逻辑。现有Service层转换方法及模型类如下:

现有Service方法

private NotificationResult convertStringToNotifyUser(List<String> records){
    List<NotifyUser> correctPhoneNumbers = new ArrayList<>();
    List<BadPhoneNumber> badPhoneNumbers = new ArrayList<>();
    for(String record: records){
        NotifyUser notifyUser = new NotifyUser();
        notifyUser.setPhone_number(record.trim());

        Errors errors = new BeanPropertyBindingResult(notifyUser, "notifyUser");
        notifyUserValidator.validate(notifyUser, errors);
        if(errors.hasErrors()){
            badPhoneNumbers.add(new BadPhoneNumber(record, errors.getFieldErrors()));
        }
        else {
            correctPhoneNumbers.add(notifyUser);
        }
    }
    return new NotificationResult(correctPhoneNumbers, badPhoneNumbers);
}

NotifyUser模型类

public class NotifyUser {
    @Id
    @Column(name = "phone_number")
    @NotEmpty(message = "Phone number cannot be empty")
    @Size(min = 11, max = 12, message = "the phone number can start with +7 or 8 and have 11 or 12 characters respectively")
    private String phone_number;

    // 其他代码
}

解决方案

利用JSR-380(Java Bean Validation)规范的验证器,自动识别模型字段上的注解完成校验,无需重复编写逻辑。

步骤1:确保依赖引入

  • 若使用Spring Boot,spring-boot-starter-web已包含hibernate-validator(JSR-380的实现),无需额外引入。
  • 若为普通Spring项目,需手动引入依赖:
    <!-- Maven -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.2.5.Final</version>
    </dependency>
    

步骤2:注入Validator并修改Service方法

通过注入javax.validation.Validator,直接调用其validate方法即可自动触发模型字段上的注解验证:

import javax.validation.Validator;
import javax.validation.ConstraintViolation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.FieldError;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class YourService {

    private final Validator validator;

    // 注入Validator
    @Autowired
    public YourService(Validator validator) {
        this.validator = validator;
    }

    private NotificationResult convertStringToNotifyUser(List<String> records){
        List<NotifyUser> correctPhoneNumbers = new ArrayList<>();
        List<BadPhoneNumber> badPhoneNumbers = new ArrayList<>();
        
        for(String record: records){
            NotifyUser notifyUser = new NotifyUser();
            notifyUser.setPhone_number(record.trim());

            // 自动验证模型字段注解
            Set<ConstraintViolation<NotifyUser>> violations = validator.validate(notifyUser);
            
            if(!violations.isEmpty()){
                // 将验证结果转换为FieldError列表,适配现有BadPhoneNumber结构
                List<FieldError> fieldErrors = violations.stream()
                        .map(violation -> new FieldError(
                                "notifyUser",
                                violation.getPropertyPath().toString(),
                                violation.getMessage()
                        ))
                        .collect(Collectors.toList());
                badPhoneNumbers.add(new BadPhoneNumber(record, fieldErrors));
            } else {
                correctPhoneNumbers.add(notifyUser);
            }
        }
        return new NotificationResult(correctPhoneNumbers, badPhoneNumbers);
    }
}

步骤3:(可选)Spring环境下配置验证器

若需要适配Spring的Validator接口,可配置LocalValidatorFactoryBean,使其支持JSR-380注解:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class ValidationConfig {
    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }
}

核心优势

  • 完全复用模型字段上的验证注解,避免逻辑重复,符合DRY原则。
  • 后续修改验证规则(如调整手机号长度、新增格式校验),仅需修改模型注解,无需改动Service层代码。
  • 自动收集所有违反注解规则的错误信息,无需手动判断空值、长度等条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 22:44:55