I have an annotation from a third-party library to which I'd like to add a custom validator implementation. Let's call it @Requirement
, and define it as follows:
@Target({PACKAGE, TYPE, METHOD, FIELD})
@Retention(RUNTIME)
@interface Requirement {}
Now I would like to add a constraint validator without adding my own annotation into the mix. I cannot do this with the XML-based ( META-INF/validation.xml
) configuration, the service loader configuration (a javax.validation.ConstraintValidator
file with my validator in it), nor can I with adding custom mappings to the HibernateValidatorConfiguration
using LocalValidatorFactoryBean
: all of these aforementioned possibilities end up checking for @Constraint
sooner or later as well.
Is there any way whatsoever to add a @Constraint
-less annotation with a validator implementation?
In my specific case, I am using Java 8 and Spring Boot 2.6.1 (which itself uses Hibernate Validator 6.2.0 and javax.validation:validation-api
2.0.1), but I am (of course) welcoming of information using any Java version and Spring version.
i think rewrite the validator implement may be achieve your goal. Below is the draft code:
@Log4j2
public class CustomHibernateValidator extends HibernateValidator {
@Override
public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) {
ValidatorFactoryImpl validatorFactory = new ValidatorFactoryImpl(configurationState);
CustomConstraintHelper customConstraintHelper = new CustomConstraintHelper();
try {
Field field = validatorFactory.getClass().getDeclaredField("constraintHelper");
field.setAccessible(true);
field.set(validatorFactory,customConstraintHelper);
} catch (IllegalAccessException | NoSuchFieldException e) {
log.error("{}",e);
}
customConstraintHelper.modify();
return validatorFactory;
}
}
class CustomConstraintHelper extends ConstraintHelper {
public CustomConstraintHelper() {
super();
}
void modify() {
Field field = null;
try {
field = this.getClass().getSuperclass().getDeclaredField("builtinConstraints");
field.setAccessible(true);
Object o = field.get(this);
Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> tmpConstraints = new HashMap<>();
tmpConstraints.putAll((Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>>) o);
//inject your validator
putConstraint(tmpConstraints, Requirement.class, RequirementValidator.class);
field.set(this, tmpConstraints);
} catch (NoSuchFieldException | IllegalAccessException e) {
}
}
private static <A extends Annotation> void putConstraint(Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> validators,
Class<A> constraintType, Class<? extends ConstraintValidator<A, ?>> validatorType) {
validators.put(constraintType, Collections.singletonList(ConstraintValidatorDescriptor.forClass(validatorType, constraintType)));
}
}
and use this implement to replace default hv via write xx.xx.CustomHibernateValidator to META-INF/services/javax.validation.spi.ValidationProvider
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.