在javax验证中使用国际化时如何插入字段名?

在javax验证中使用国际化时如何插入字段名?,java,spring,spring-boot,internationalization,bean-validation,Java,Spring,Spring Boot,Internationalization,Bean Validation,我将javax验证注释用于Spring引导和国际化。因此,我有以下字段: @Size(min = 3, max = 3, message = "{javax.validation.constraints.Size.message}") private String currencyCode; 美国资源包包括: javax.validation.constraints.Size.message = size must be between {min} and {max} 因此,当该字段验证失败

我将javax验证注释用于Spring引导和国际化。因此,我有以下字段:

@Size(min = 3, max = 3, message = "{javax.validation.constraints.Size.message}")
private String currencyCode;
美国资源包包括:

javax.validation.constraints.Size.message = size must be between {min} and {max}
因此,当该字段验证失败时,我会看到消息
“大小必须介于3和3之间”

但我想要的是这样一个信息:

javax.validation.constraints.Size.message = {fieldName}'s size must be between {min} and {max}
这将导致消息
“currencyCode的大小必须介于3和3之间”


这可能吗?我需要重写bean才能使其工作吗?字段名是否有预定义属性?

您可以为MethodArgumentNotValidException创建处理程序

@ExceptionHandler(MethodArgumentNotValidException.class)
public Object handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) { ...
在它们内部,您可以调用

 e.getBindingResult().getFieldErrors();
此集合包含有关无效字段错误的所有信息,例如字段名、拒绝值

接下来,使用示例中的消息,并使用org.apache.commons.lang3中的StrSubstitutor。只需创建参数映射

键-->字段名,值-->货币代码


当然,您必须编写一些代码,但解决方案如下:)

默认情况下@Size annotation不提供在消息中放置标签的选项,相反,您可以创建自己的实现,如下所示,以便在整个应用程序中使用它:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = MySizeValidator.class)
public @interface MySize {

    String message() default "{javax.validation.constraints.Size.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    int min() default 0;

    int max() default Integer.MAX_VALUE;

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {

        Size[] value();
    }

    public abstract String label();
}

你说使用StrSubstitutor是什么意思?谢谢,这基本上就是答案。我将只使用
fieldError.getDefaultMessage().replace(“{fieldName}”,fieldError.getField())我的意思是映射值Map=HashMap();价值Map.put(“动物”、“快速棕色狐狸”);价值映射放置(“目标”、“懒狗”);String templateString=“${animal}跳过${target}。”;StrSubstitutor sub=新的StrSubstitutor(值MAP);String resolvedString=sub.replace(templateString)
和result
敏捷的棕色狐狸跳过了懒惰的狗。
但是你的解决方案也很好。在该解决方案中,你需要为eg正确设置标签格式;在POJO中,fieldName是currencyCode,但是您必须在屏幕上显示“货币代码”,然后如果字段currencyCode出现,您需要在某处放置一个映射,然后用货币代码替换它。还有一个问题是,如果您有两个POJO,它们具有相同的字段名和不同的描述,比如一次您希望将标签返回为“当前代码”,另一次您希望将标签返回为“货币”,那么黑客解决方案将是混乱的,尽管创建自己的验证器/注释是spring使用的一个干净的解决方案,但这是您的职责,但我认为提供一个干净的解决方案标签应该是客户端的事情,而不是由服务器驱动的。但是你的观点是正确的。@AmitKBist你的解决方案更好,但是common
@Size
注释已经过测试,等等。一般来说,我认为为模型创建自己的验证器要比为该模型中的字段创建注释/attrib好得多。注释破坏了OOP,但所需时间更少。悲伤但真实。
public class MySizeValidator implements ConstraintValidator<MySize, String> {

    private static final Log log = LoggerFactory.make();

    private int min;
    private int max;

    @Override
    public void initialize(MySize parameters) {
        min = parameters.min();
        max = parameters.max();
        validateParameters();
    }

    @Override
    public boolean isValid(String field, ConstraintValidatorContext constraintValidatorContext) {
        if (field == null) {
            return true;
        }
        int length = field.length();
        return length >= min && length <= max;
    }

    private void validateParameters() {
        if (min < 0) {
            throw log.getMinCannotBeNegativeException();
        }
        if (max < 0) {
            throw log.getMaxCannotBeNegativeException();
        }
        if (max < min) {
            throw log.getLengthCannotBeNegativeException();
        }
    }
}
@MySize(min = 3, max = 3, message = "{javax.validation.constraints.mySize.message}", label = "Currency Code")
    private String currencyCode;