Как получить текст ошибки в контроллере от BindingResult
У меня есть контроллер, который возвращает JSON. Он принимает форму, которая проверяет себя через аннотации spring. Я могу получить список FieldError из BindingResult, но они не содержат текст, который JSP будет показывать в теге. Как я могу получить текст ошибки для отправки обратно в JSON?
@RequestMapping(method = RequestMethod.POST)
public
@ResponseBody
JSONResponse submit(@Valid AnswerForm answerForm, BindingResult result, Model model, HttpServletRequest request, HttpServletResponse response) {
if (result.hasErrors()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
JSONResponse r = new JSONResponse();
r.setStatus(JSONResponseStatus.ERROR);
//HOW DO I GET ERROR MESSAGES OUT OF BindingResult???
} else {
JSONResponse r = new JSONResponse();
r.setStatus(JSONResponseStatus.OK);
return r;
}
}
Класс JSONREsponse - это просто POJO
public class JSONResponse implements Serializable {
private JSONResponseStatus status;
private String error;
private Map<String,String> errors;
private Map<String,Object> data;
...getters and setters...
}
Вызов BindingResult.getAllErrors() возвращает массив объектов FieldError, но он не имеет фактических ошибок.
Ответы
Ответ 1
Отказ от ответственности: я до сих пор не использую Spring -MVC 3.0
Но я думаю, что тот же подход, используемый Spring 2.5, может полностью удовлетворить ваши потребности
for (Object object : bindingResult.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
System.out.println(fieldError.getCode());
}
if(object instanceof ObjectError) {
ObjectError objectError = (ObjectError) object;
System.out.println(objectError.getCode());
}
}
Я надеюсь, что это может быть полезно для вас.
UPDATE
Если вы хотите получить сообщение, предоставленное вашим ресурсным пакетом, вам понадобится зарегистрированный экземпляр messageSource (It must будет называться messageSource)
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="ValidationMessages"/>
</bean>
Внесите свой экземпляр MessageSource внутри вашего представления
@Autowired
private MessageSource messageSource;
И чтобы получить ваше сообщение, сделайте следующее
for (Object object : bindingResult.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
/**
* Use null as second parameter if you do not use i18n (internationalization)
*/
String message = messageSource.getMessage(fieldError, null);
}
}
Ваш валидатор должен выглядеть как
/**
* Use null as fourth parameter if you do not want a default message
*/
errors.rejectValue("<FIELD_NAME_GOES_HERE>", "answerform.questionId.invalid", new Object [] {"123"}, null);
Ответ 2
Недавно я встретил эту проблему и нашел более простой способ (возможно, это поддержка Spring 3)
List<FieldError> errors = bindingResult.getFieldErrors();
for (FieldError error : errors ) {
System.out.println (error.getObjectName() + " - " + error.getDefaultMessage());
}
Нет необходимости изменять/добавлять источник сообщения.
Ответ 3
С потоками Java 8
bindingResult
.getFieldErrors()
.stream()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));
Ответ 4
BEAN XML:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
<bean id="messageAccessor" class="org.springframework.context.support.MessageSourceAccessor">
<constructor-arg index="0" ref="messageSource"/>
</bean>
JAVA:
for (FieldError error : errors.getFieldErrors()) {
logger.debug(messageAccessor.getMessage(error));
}
ПРИМЕЧАНИЕ. Вызов Errors.getDefaultMessage() не обязательно будет возвращать то же сообщение, которое генерируется из кода + args. Значение по умолчаниюMessage - это отдельное значение, определенное при вызове метода Errors.rejectValue(). См. API Errors.rejectValue() здесь
Ответ 5
WebMvcConfigurerAdapter:
@Bean(name = "messageSourceAccessor")
public org.springframework.context.support.MessageSourceAccessor messageSourceAccessor() {
return new MessageSourceAccessor( messageSource());
}
Контроллер:
@Autowired
@Qualifier("messageSourceAccessor")
private MessageSourceAccessor messageSourceAccessor;
...
StringBuilder sb = new StringBuilder();
for (ObjectError error : result.getAllErrors()) {
if ( error instanceof FieldError) {
FieldError fe = (FieldError) error;
sb.append( fe.getField());
sb.append( ": ");
}
sb.append( messageSourceAccessor.getMessage( error));
sb.append( "<br />");
}