Возможно, вы уже знаете, что сообщения для проверки бинов определены в Resource Bundle ValidationMessages.properties
в корне ваших классов (т. Е. WEB-INF\classes\ValidationMessages.properties
).
Эти сообщения могут иметь параметры, но не имеютработать как в JSF.Существует интерфейс под названием MessageInterpolator
, который преобразует шаблон сообщения в фактическое сообщение.
Интерполятор по умолчанию работает с именованными параметрами, как в сообщении: Значение должно быть между {min} и {max} .Значения между { и } разрешаются первыми в пакете ресурсов приложения;позже в пакете ресурсов провайдера и последним в свойствах аннотации ограничения.(Это более или менее работает, полный алгоритм приведен в разделе 4.3 спецификации проверки компонентов).
Предположим, вы определяете сообщение атрибута аннотации Size как {creditCard.message}
Содержимое файла ValidationMessage.properties может иметь значение
creditCard.message=Credit card length must be at least {min} characters. \
Thank you for choosing the plantsvszombies credit card.
Вы можете заменить заводыvszombies свойством:
creditCard.message=Credit card length must be at least {min} characters. \
Thank you for choosing the {creditCard.type} credit card.
creditCard.type=plantsvszombies
Вы можете даже использовать два параметра всообщение об ограничении
Size(min=13, message="{creditCard.message} {plantsvszombies.messages}")
и определите пакет ресурсов как
creditCard.message=Credit card length must be at least {min} characters.
plantsvszombies.message=Thank you for choosing the plantsvszombies credit card.
Я думаю, что это простой и чистый подход.
Но если выхотите что-то большее, например, определение пользовательских параметров в объявлении ограничения, вы можете использовать пользовательский интерполятор сообщений. Обратите внимание, что это может быть более хитрым решением .
Что ж, вы можете определить синтаксис для представления ваших параметров в строке сообщения.Затем пусть интерполятор по умолчанию разрешит сообщение.Синтаксис пользовательских параметров не будет понят интерполятором по умолчанию, и он останется там после разрешения.Затем пользовательский интерполятор может заменить и заменить пользовательские параметры.
Это проще понять на примере.
Во-первых, сообщение определяется как {creditCard.message} [plantsvszombies] .Для этого синтаксиса содержимое в квадратных скобках - это индексированные параметры, разделенные запятыми (здесь только один параметр).
Далее содержимое пакета ресурсов определяется с помощью:
creditCard.message=Credit card length must be at least {min} characters. \
Thank you for choosing the {0} credit card.
Когда интерполятор по умолчанию заменяет первую часть выражения, у нас будет:
Длина кредитной карты должна быть не менее 13 символов.\ Благодарим Вас за выбор кредитной карты {0}. [Plantvszombies]
Затем пользовательский интерполятор возьмет последнее выражение и разделит содержимое, чтобы получить токены, и заменит индексированные параметры токеном.в соответствующем индексе (параметр [0] = plantvzzombies).
Таким образом, сообщение будет:
Длина кредитной карты должна быть не менее 13 символов.\ Спасибо за выбор кредитной карты plantvszombies.
Это код пользовательского интерполятора для этого синтаксиса (не оптимизирован, и шаблон регулярного выражения не может работать, если в первом выражении есть другие квадратные скобки).или в токенах).
package validation;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.validation.MessageInterpolator;
import javax.validation.Validation;
public class MyInterpolator implements MessageInterpolator{
private MessageInterpolator interpolator;
public MyInterpolator() {
//we need to delegate to the default interpolator
this.interpolator = Validation.byDefaultProvider().configure().getDefaultMessageInterpolator();
}
private static final Pattern parametersPattern=Pattern.compile("\\[(.+)\\]$");
protected static String replaceParameters(String message){
Matcher matcher = parametersPattern.matcher(message);
String values[]={};
if(matcher.find()){
values=matcher.group(1).split("\\s*,\\s*");
message=message.substring(0, matcher.start());
for(int i=0; i < values.length; i++){
message=message.replace("{"+i+"}", values[i]);
}
}
return message;
}
@Override
public String interpolate(String messageTemplate, Context context) {
String message = interpolator.interpolate(messageTemplate, context);
return replaceParameters(message);
}
@Override
public String interpolate(String messageTemplate, Context context, Locale locale) {
String message = interpolator.interpolate(messageTemplate, context);
return replaceParameters(message);
}
}
Регистрация интерполятора происходит в XML-файле с именем META-INF / validation.xml (4.4.6 спецификации).
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">
<message-interpolator>validation.MyInterpolator</message-interpolator>
</validation-config>
Это немного сложное решение, потому что аннотации ограничений не принимают параметры для сообщений и потому что в интерполяторе мы не можем получить много информации о проверяемом свойстве.Если я найду более простое решение, я опубликую его.