Основанная на аннотации проверка бина Spring
Я исследую основанный на аннотациях подход к валидации Spring-компонентов с использованием Spring- модулей. В этом руководстве в качестве примера используется следующий компонент (методы getter и setters опущены):
public final class User {
@NotBlank
@Length(max = 80)
private String name;
@NotBlank
@Email
@Length(max = 80)
private String email;
@NotBlank
@Length(max = 4000)
private String text;
}
Сообщение об ошибке, которое используется, если определенное правило проверки не соблюдается, должно иметь следующий формат:
bean-class.bean-propery[validation-rule]=Validation Error message
Примеры для класса, показанного выше, включают:
User.email[not.blank]=Please enter your e-mail address.
User.email[email]=Please enter a valid e-mail address.
User.email[length]=Please enter no more than {2} characters.
Тот факт, что ключи сообщения содержат имя класса, создает пару проблем:
- Если класс переименован, ключи сообщения также должны быть изменены
Если у меня есть другой класс (например, Person) со свойством электронной почты, которое проверяется идентично User.email, мне нужно продублировать сообщения, например
Person.email[not.blank]= Пожалуйста, введите свой адрес электронной почты.
Person.email [email] = Пожалуйста, введите действительный адрес электронной почты.
Person.email [длина] = Пожалуйста, введите не более {2} символов.
Фактически, в документации утверждается, что возможно настроить сообщение по умолчанию для определенного правила (например, @Email), например:
email=email address is invalid
Это сообщение по умолчанию следует использовать, если не удается найти специфическое для bean-сообщения сообщение для правила. Однако мой опыт показывает, что это просто не работает.
Альтернативный механизм, позволяющий избежать дублирования сообщений, заключается в передаче ключа сообщения об ошибке в аннотацию правила. Например, предположим, что я определил следующее сообщение об ошибке по умолчанию для правила @Email
badEmail=Email address is invalid
Это сообщение следует использовать, если я аннотирую соответствующее свойство следующим образом:
@Email(errorCode="badEmail")
private String email;
Тем не менее, я пробовал это время от времени, это просто не похоже на работу. Кто-нибудь нашел способ избежать дублирования сообщений об ошибках при использовании этой структуры проверки?
3 ответа
Я быстро взглянул на API BeanValidator, и, похоже, вы захотите попробовать свойство errorCodeConverter.
Вам нужно будет реализовать свой собственный ErrorCodeConverter или использовать одну из предоставленных реализаций?
....
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
p:configurationLoader-ref="configurationLoader"
p:errorCodeConverter-ref="errorCodeConverter" />
<bean id="errorCodeConverter" class="contact.MyErrorCodeConverter" />
....
Примечание. ConfigurationLoader - это еще один компонент, определенный в XML-файле конфигурации, который используется в руководстве.
Пример конвертера:
package contact;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springmodules.validation.bean.converter.ErrorCodeConverter;
public class MyErrorCodeConverter implements ErrorCodeConverter {
private Log log = LogFactory.getLog(MyErrorCodeConverter.class);
@Override
public String convertPropertyErrorCode(String errorCode, Class clazz, String property) {
log.error(String.format("Property %s %s %s", errorCode, clazz.getClass().getName(), property));
return errorCode; // <------ use the errorCode only
}
@Override
public String convertGlobalErrorCode(String errorCode, Class clazz) {
log.error(String.format("Global %s %s", errorCode, clazz.getClass().getName()));
return errorCode;
}
}
Теперь свойства должны работать:
MyEmailErrorCode=Bad email
class Foo {
@Email(errorCode="MyEmailErrorCode")
String email
}
В Spring validation есть ErrorCodeConverter, который делает это:
org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter
Когда это используется, пакет ресурсов будет проверен на наличие следующих кодов:
[errorCode.commandBeanName.fieldName, errorCode.fieldName, errorCode.fieldClassName, errorCode]
- errorCode - это фактический код ошибки, например. not.blank, электронная почта.
- commandBeanName совпадает с именем ключа модели, который ссылается на компонент поддержки формы.
- fieldName - это имя поля.
- fieldClassName - имя класса поля, например. java.lang.String, java.lang.Integer
Так, например, если у меня есть bean-компонент, на который ссылается в модели ключ "formBean", а поле emailAddress типа java.lang.String не содержит адрес электронной почты, который вызывает ошибку errorCode. Среда проверки будет пытаться разрешить следующие коды сообщений:
[email.formBean.emailAddress, email.emailAddress, email.java.lang.String, email]
Если errorCode заменен errorCode "badEmail" следующим образом:
@Email (ERRORCODE ="badEmail")
Коды сообщений, которые фреймворк попытается разрешить, будут:
[badEmail.formBean.emailAddress, badEmail.emailAddress, badEmail.java.lang.String, badEmail]
Я бы посоветовал оставить код ошибки таким же. Таким образом, одно сообщение может использоваться для всех полей, с которыми связан этот код ошибки. Если вам нужно быть более конкретным с сообщением для определенного поля, вы можете добавить сообщение к пакетам ресурсов с кодом errorCode.commandBeanName.field.
Добавьте следующие бобы в свой applicationContext.xml
файл.
<bean id="configurationLoader"
class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader" />
<!-- Use the error codes as is. Don't convert them to <Bean class name>.<bean field being validated>[errorCode]. -->
<bean id="errorCodeConverter"
class="org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter"/>
<!-- shortCircuitFieldValidation = true ==> If the first rule fails on a field, no need to check
other rules for that field -->
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
p:configurationLoader-ref="configurationLoader"
p:shortCircuitFieldValidation="true"
p:errorCodeConverter-ref="errorCodeConverter"/>