能否在自定义Java类型MyType上使用标准约束注解@Size?
问题原因
@Size注解默认仅支持String、Collection、Map、数组等类型,自定义的MyType不在其默认支持范围内,因此hibernate-validator-annotation-processor会在编译阶段抛出类型不匹配的错误。
解决方案
要让标准@Size注解能直接应用在MyType类型字段上,需要从运行时验证支持和编译时注解处理器兼容两方面处理:
1. 实现自定义ConstraintValidator
编写一个验证器,让@Size能识别MyType类型,并提取其内部的byte[]属性进行大小校验:
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import jakarta.validation.constraints.Size; public class MyTypeSizeValidator implements ConstraintValidator<Size, MyType> { private int min; private int max; @Override public void initialize(Size constraintAnnotation) { this.min = constraintAnnotation.min(); this.max = constraintAnnotation.max(); } @Override public boolean isValid(MyType value, ConstraintValidatorContext context) { // @Size默认允许null值,若需非空校验需额外添加@NotNull if (value == null) { return true; } byte[] content = value.getValue(); // 确保MyType有公开的getValue()方法获取内部byte[] return content.length >= min && content.length <= max; } }
2. 注册验证器
方式A:SPI自动注册(推荐)
在项目的src/main/resources/META-INF/services目录下创建文件jakarta.validation.ConstraintValidator,写入你的验证器全类名:
com.yourpackage.MyTypeSizeValidator
Hibernate Validator会通过服务加载机制自动识别并启用该验证器。
方式B:Spring环境程序式注册
如果是Spring项目,也可以通过配置类手动注册:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @Configuration public class ValidatorConfig { @Bean public LocalValidatorFactoryBean validator() { LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); factoryBean.getConstraintValidatorFactory().addConstraintValidator(Size.class, MyType.class, new MyTypeSizeValidator()); return factoryBean; } }
3. 解决编译时注解处理器报错
创建约束映射文件,告诉hibernate-validator-annotation-processor:@Size支持MyType类型。在src/main/resources/META-INF/validation/constraint-mappings.xml中添加以下内容:
<?xml version="1.0" encoding="UTF-8"?> <constraint-mappings xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/validation-mapping-3.0.xsd" version="3.0"> <constraint-definition annotation="jakarta.validation.constraints.Size"> <validated-by> <value>com.yourpackage.MyTypeSizeValidator</value> </validated-by> <target> <value>com.yourpackage.MyType</value> </target> </constraint-definition> </constraint-mappings>
备选方案:嵌套验证(不推荐,不符合需求)
如果不想扩展@Size的支持范围,也可以在MyType内部的byte[]字段上直接添加@Size,然后在DTO的MyType字段上添加@Valid触发嵌套验证:
public class MyType { @Size(max = 100) private byte[] value; // getter、setter方法 } public class SampleDTO { @Valid public MyType fileContent; }
但此方案需要修改MyType的内部实现,无法让使用者直接在MyType字段上使用@Size,仅作为备选。
内容的提问来源于stack exchange,提问作者bobbyrne01

