我正在使用Hibernate Validator,并且想在错误消息中解析类别的名称。考虑以下简单情况:
public class Category { private String name; } public class Product { @HazardousCategoryConstraint(message = "{haz.cat.error}") private Category category; private String name; } public class InventoryReport { @Valid private List<Product> products; } ValidationMessages.properties haz.cat.error={name} is a product in the hazardous category list.
假设我有一个HazardousCategoryConstraint的有效实现。验证器根据受限名称列表检查每个类别的名称。当我调用validate(InventoryReport)时,我得到了我期望的错误数量,但它们是相同的字符串。我希望看到类别名称解析为每条消息。有人可以给我指出一个如何动态解析参数的示例,或向我展示如何进行解析吗?
IMO,简单的解决方案是创建的自定义实现javax.validation.MessageInterpolator。将主要工作委托给Hibernate Validator ResourceBundleMessageInterpolator,并在中进行所需的替换工作CustomMessageInterpolator。
javax.validation.MessageInterpolator
ResourceBundleMessageInterpolator
CustomMessageInterpolator
public class CustomMessageInterpolator extends org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator { private static final Pattern MESSAGE_PARAMETER_PATTERN = Pattern.compile( "(\\{[^\\}]+?\\})" ); @Override public String interpolate(String message, Context context) { String resolvedMessage = super.interpolate(message, context); resolvedMessage = replacePropertyNameWithPropertyValues(resolvedMessage, context.getValidatedValue()); return resolvedMessage; } private String replacePropertyNameWithPropertyValues(String resolvedMessage, Object validatedValue) { Matcher matcher = MESSAGE_PARAMETER_PATTERN.matcher( resolvedMessage ); StringBuffer sb = new StringBuffer(); while ( matcher.find() ) { String parameter = matcher.group( 1 ); String propertyName = parameter.replace("{", ""); propertyName = propertyName.replace("}", ""); PropertyDescriptor desc = null; try { desc = new PropertyDescriptor(propertyName, validatedValue.getClass()); } catch (IntrospectionException ignore) { matcher.appendReplacement( sb, parameter ); continue; } try { Object propertyValue = desc.getReadMethod().invoke(validatedValue); matcher.appendReplacement( sb, propertyValue.toString() ); } catch (Exception ignore) { matcher.appendReplacement( sb, parameter ); } } matcher.appendTail( sb ); return sb.toString(); } }
@测试
public void validate() { Configuration<?> configuration = Validation.byDefaultProvider().configure(); ValidatorFactory validatorFactory = configuration.messageInterpolator(new CustomMessageInterpolator()).buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); Product p = new Product(); Category cat = new Category(); cat.setName("s"); //assume specified name is invalid p.setCategory(cat); Set<ConstraintViolation<Product>> violations = validator.validate(p); for(ConstraintViolation<Product> violation : violations) { System.out.println(violation.getMessage()); } }
输出量
s is a product in the hazardous category list.