如何从 BindingResult 获取控制器中的错误文本
Posted
技术标签:
【中文标题】如何从 BindingResult 获取控制器中的错误文本【英文标题】:How to get error text in controller from BindingResult 【发布时间】:2011-02-14 15:33:03 【问题描述】:我有一个返回 JSON 的控制器。它采用一个表单,通过 spring 注释验证自己。我可以从 BindingResult 获取 FieldError 列表,但它们不包含 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());
希望对你有用
更新
如果你想获取你的资源包提供的消息,你需要一个注册的messageSource实例(它必须被称为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);
【讨论】:
假设我在 ValidationMessages.properties 中有以下内容:“answerform.questionId.invalid = 无效的问题 ID:0。” fieldError.getCode() 将返回“answerform.questionId.invalid”,我正在寻找错误本身,而不是代码,例如:“Invalid question id: 123” 谢谢这对我有帮助...如果使用国际化,那么只需传递语言环境(如果需要,还可以传递参数)以获取翻译后的字符串以放置在您的 JSON 错误对象中:messageSource.getMessage (fieldError.getCode( ), fieldError.getArguments(), myQuestionnaire.getLocale ())【参考方案2】:最近遇到这个问题,找到了更简单的方法(可能是Spring 3的支持)
List<FieldError> errors = bindingResult.getFieldErrors();
for (FieldError error : errors )
System.out.println (error.getObjectName() + " - " + error.getDefaultMessage());
无需更改/添加消息源。
【讨论】:
@J.Wincewicz:很抱歉没有批准您的编辑建议。上面的代码是我在 Spring 3 中测试(并运行)的。您的代码建议使用一种新方法,我不能 100% 确定它是否适用于这个旧版本的 Spring。不过,您可以将其作为单独的答案或 cmets 发布在此帖子上。【参考方案3】:使用 Java 8 流
bindingResult
.getFieldErrors()
.stream()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));
【讨论】:
'stream().forEach()' 链可以替换为 'forEach()' docs.oracle.com/javase/8/docs/api/java/lang/…【参考方案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() 不一定会返回从代码 + 参数生成的相同消息。 defaultMessage 是调用 Errors.rejectValue() 方法时定义的单独值。见Errors.rejectValue() API Here
【讨论】:
【参考方案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 />");
【讨论】:
或许更详细的解释会有所帮助。【参考方案6】:要获取与每个字段相关的所有错误的Map
:
@Autowired
private MessageSource messageSource;
Map<String, List<String>> errorMap = bindingResult.getFieldErrors().stream()
.collect(Collectors.groupingBy(FieldError::getField,
Collectors.mapping(e -> messageSource.getMessage(e, LocaleContextHolder.getLocale()),
Collectors.toList())));
//In this example, each field/key is mapped to a
//List of all the errors associated with that field
要获得一个Map
,其中与每个字段相关的错误合并为一个String
:
@Autowired
private MessageSource messageSource;
Map<String, String> errorMap = bindingResult.getFieldErrors().stream()
.collect(Collectors
.toMap(FieldError::getField,
e -> messageSource.getMessage(e, LocaleContextHolder.getLocale()),
(a,b)->a + "<br/>" + b));
//In this example, multiple errors for the same field are separated with <br/>,
//the line break element, to be easily displayed on the front end
【讨论】:
以上是关于如何从 BindingResult 获取控制器中的错误文本的主要内容,如果未能解决你的问题,请参考以下文章
将 JSR-303 验证错误转换为 Spring 的 BindingResult