java - javax.validation.constraints.Pattern 注释的参数化错误消息?

  显示原文与译文双语对照的内容
0 0

我有一个类型为 String的实体,在它的上我定义了一个 @Pattern 注释,实施与给定正则表达式匹配的。 现在我想知道,是否可以参数化约束,例如没有匹配正则表达式的第一个字符显示在。

更糟糕的是,为约束冲突显示的错误消息直接在注释中定义,但在属性文件中如下所示:

示例类:


public class Address {
 @Pattern(regexp="[a-zA-Z]*", message="paremeterizedMessage")
 private String street;
}

示例属性 file:


parameterizedMessage = Invalid character {0}. Only characters a-z, A-Z allowed.

可以用 javax.validation 做这样的事情? 我认为 @Pattern 注释不能参数化错误消息。 但是,也许可以用参数化的验证消息定义我自己的ConstraintValidator

时间: 原作者:

0 0

考虑到一些验证注释( 比如 @Size(min=1,max=5) ) 允许使用参数化的错误消息,比如 The String must have a length of {min} to {max} characters. 我发现一个解决方案的错误消息通常与地方持有者,如 {0}{1},。"。"。:

定义一个自己的验证约束,例如:


@Constraint(validatedBy=OnlyCharactersAllowedValidator.class)
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OnlyCharactersAllowed {
 String message() default"parameterizedMessage";
 Class<?>[] groups() default {};
 Class<? extends Payload>[] payload() default {};
}

可以使用反射reflection扩展映射来存储所有注释参数( 例如 minmax@Size ),并且可以为键 0 添加附加参数,例如:


public class OnlyCharactersAllowedValidator implements ConstraintValidator<OnlyCharactersAllowed,String>
{
 private static final String validCharacters ="abcdefghijklmnopqrstuvwxyz";
 @Override
 public boolean isValid(String text, ConstraintValidatorContext constraintContext)
 {
 for (int index = 0; index <text.length; index++) {
 String aCharacter = text.substring(index, index+1);
 if (text.indexOf(aCharacter) <0) {
/* Within this message call the magic happens: {0} is mapped to the invalid character. */
 addMessageParameter(constraintContext, aCharacter);
/* Create violation message manually and suppress the default message. */constraintContext.buildConstraintViolationWithTemplate(constraintContext.getDefaultConstraintMessageTemplate()).addConstraintViolation();
 constraintContext.disableDefaultConstraintViolation();
/* No further validation: show only one error message for invalid characters. */
 break;
 }
 }
 }

 private void addMessageParameter(ConstraintValidatorContext constraintContext, Object... parameter)
 {
 try
 {
/* Get map for parameters (reflection necessary). */
 Field descriptorField = ConstraintValidatorContextImpl.class.getDeclaredField("constraintDescriptor");
 descriptorField.setAccessible(true);
 @SuppressWarnings("unchecked")
 ConstraintDescriptorImpl<OnlyCharactersAllowed> descriptor = (ConstraintDescriptorImpl<OnlyCharactersAllowed>) descriptorField.get(constraintContext);

 Map<String,Object> attributes = descriptor.getAttributes();

/* Copy immutable Map to new Map. */
 Map<String,Object> newAttributes = new HashMap<String,Object>(attributes.size() + parameter.length);
 for (String key : attributes.keySet())
 {
 newAttributes.put(key, attributes.get(key));
 }

/* Add given parameters to attributes. */
 Integer parameterCounter = 0;
 for (Object param : parameter)
 {
 newAttributes.put(parameterCounter.toString(), param);
 parameterCounter++;
 }

/* Set new Map in Descriptor (reflection necessary). */
 Field attributesField = ConstraintDescriptorImpl.class.getDeclaredField("attributes");
 attributesField.setAccessible(true);
 attributesField.set(descriptor, newAttributes);
 }
 catch (NoSuchFieldException | IllegalAccessException | SecurityException | ClassCastException e1)
 {
/* Do nothing in case of exception. Unparameterized message is shown. */
 }
 }
}

如果在属性文件中定义了验证消息,这样的解决方案甚至可以。


parameterizedMessage = Invalid character: Do not use the {0} character.

原作者:
...