如何从约束描述符手动评估休眠验证器消息模板?
how to manually evaluate hibernate validator message templates from constraint descriptor?
我成功地使用 Hibernate Validator 来验证请求 POJO。 getter 上的注释在某种程度上是自我记录的,因此有人可以仔细阅读生成的 javadoc 以了解约束是什么。
我觉得这对于有效的文档来说还不够好。我正在尝试编写一个 Javadoc 自定义 Taglet,它对包含 class 的当前内容进行内省,并在 class.
中构建一个 HTML table 属性约束
我实际上已经能够为每个受约束的 属性 获取 ConstraintDescriptor。我想要做的是插入 "messageTemplate" 以生成可读字符串。
例如,如果 属性 有一个 @Size 注释,我可以找到关于这个 ConstraintDescriptor 的信息,并且 "messageTemplate" 属性 的值为“ {javax.validation.constraints.Size.message}”。我需要得到的是像 "must be between X and Y" 这样的消息(或类似的东西)。如果该字符串具有指定的实际 "min" 和 "max" 值,那就太好了,但如果它说 "must be between {min} and {max} ..." 我会接受的。
唯一似乎接近的是 ValidatorFactory 的 "messageInterpolator" 属性,以及它的 "interpolate()" 方法。问题是,除了消息模板之外,该方法还需要一个 "Context" 对象。这当然是可以理解的,因为它必须从类似的东西中获取 "min" 和 "max" 之类的参数,但我不明白我必须在这里提供什么。
到目前为止我的代码看起来有点像这样:
ValidatorFactory validatorFactory =
Validation.
byProvider(HibernateValidator.class).
providerResolver(new HibernateValidatorProviderResolver()).
configure().
externalClassLoader(getClass().getClassLoader()).
messageInterpolator(new ResourceBundleMessageInterpolator(
new PlatformResourceBundleLocator(ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES),
true, buildExpressionFactory())).
buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
BeanDescriptor constraintsForClass = validator.getConstraintsForClass(clazz);
System.out.println("constraintsForClass[" + constraintsForClass +
"] hasConstraints[" + constraintsForClass.hasConstraints() + "]");
if (constraintsForClass.hasConstraints()) {
for (ConstraintDescriptor<?> constraintDescriptor : constraintsForClass.getConstraintDescriptors()) {
System.out.println("constraintDescriptor[" + constraintDescriptor + "]");
emitTableRow(sb, "", constraintDescriptor);
}
}
for (PropertyDescriptor propertyDescriptor : constraintsForClass.getConstrainedProperties()) {
System.out.println("propertyDescriptor[" + propertyDescriptor +
"] name[" + propertyDescriptor.getPropertyName() + "]");
for (ConstraintDescriptor<?> constraintDescriptor : propertyDescriptor.getConstraintDescriptors()) {
System.out.println("constraintDescriptor[" + constraintDescriptor +
"] mt[" + constraintDescriptor.getMessageTemplate() + "]");
String interpolatedStr = validatorFactory.getMessageInterpolator().interpolate(constraintDescriptor.getMessageTemplate(), null);
System.out.println("interpolatedStr[" + interpolatedStr + "]");
如您所见,我目前将 "null" 作为第二个参数传递给 "interpolate()",这会导致“org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver.getVariable(Context, String)
”中的 NPE。
您可以尝试传入 MessageInterpolator.Context
的虚拟实现,其中 returns 您手中的描述符,验证值为 null。
我成功地使用 Hibernate Validator 来验证请求 POJO。 getter 上的注释在某种程度上是自我记录的,因此有人可以仔细阅读生成的 javadoc 以了解约束是什么。
我觉得这对于有效的文档来说还不够好。我正在尝试编写一个 Javadoc 自定义 Taglet,它对包含 class 的当前内容进行内省,并在 class.
中构建一个 HTML table 属性约束我实际上已经能够为每个受约束的 属性 获取 ConstraintDescriptor。我想要做的是插入 "messageTemplate" 以生成可读字符串。
例如,如果 属性 有一个 @Size 注释,我可以找到关于这个 ConstraintDescriptor 的信息,并且 "messageTemplate" 属性 的值为“ {javax.validation.constraints.Size.message}”。我需要得到的是像 "must be between X and Y" 这样的消息(或类似的东西)。如果该字符串具有指定的实际 "min" 和 "max" 值,那就太好了,但如果它说 "must be between {min} and {max} ..." 我会接受的。
唯一似乎接近的是 ValidatorFactory 的 "messageInterpolator" 属性,以及它的 "interpolate()" 方法。问题是,除了消息模板之外,该方法还需要一个 "Context" 对象。这当然是可以理解的,因为它必须从类似的东西中获取 "min" 和 "max" 之类的参数,但我不明白我必须在这里提供什么。
到目前为止我的代码看起来有点像这样:
ValidatorFactory validatorFactory =
Validation.
byProvider(HibernateValidator.class).
providerResolver(new HibernateValidatorProviderResolver()).
configure().
externalClassLoader(getClass().getClassLoader()).
messageInterpolator(new ResourceBundleMessageInterpolator(
new PlatformResourceBundleLocator(ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES),
true, buildExpressionFactory())).
buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
BeanDescriptor constraintsForClass = validator.getConstraintsForClass(clazz);
System.out.println("constraintsForClass[" + constraintsForClass +
"] hasConstraints[" + constraintsForClass.hasConstraints() + "]");
if (constraintsForClass.hasConstraints()) {
for (ConstraintDescriptor<?> constraintDescriptor : constraintsForClass.getConstraintDescriptors()) {
System.out.println("constraintDescriptor[" + constraintDescriptor + "]");
emitTableRow(sb, "", constraintDescriptor);
}
}
for (PropertyDescriptor propertyDescriptor : constraintsForClass.getConstrainedProperties()) {
System.out.println("propertyDescriptor[" + propertyDescriptor +
"] name[" + propertyDescriptor.getPropertyName() + "]");
for (ConstraintDescriptor<?> constraintDescriptor : propertyDescriptor.getConstraintDescriptors()) {
System.out.println("constraintDescriptor[" + constraintDescriptor +
"] mt[" + constraintDescriptor.getMessageTemplate() + "]");
String interpolatedStr = validatorFactory.getMessageInterpolator().interpolate(constraintDescriptor.getMessageTemplate(), null);
System.out.println("interpolatedStr[" + interpolatedStr + "]");
如您所见,我目前将 "null" 作为第二个参数传递给 "interpolate()",这会导致“org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver.getVariable(Context, String)
”中的 NPE。
您可以尝试传入 MessageInterpolator.Context
的虚拟实现,其中 returns 您手中的描述符,验证值为 null。