如何不使用@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
相关产品推荐
相关产品推荐

