如何从 BindingResult 获取控制器中的错误文本?

发布于 2024-08-30 20:45:29 字数 1289 浏览 9 评论 0原文

我有一个返回 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 对象数组,但它没有实际的错误。

I have an controller that returns JSON. It takes a form, which validates itself via spring annotations. I can get FieldError list from BindingResult, but they don't contain the text that a JSP would display in the <form:errors> tag. How can I get the error text to send back in 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 class is just a 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...
}

Calling BindingResult.getAllErrors() returns an array of FieldError objects, but it does not have the actual errors.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

薯片软お妹 2024-09-06 20:45:29

免责声明:我仍然不使用 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);

Disclaimer: I still do not use Spring-MVC 3.0

But i think the same approach used by Spring 2.5 can fullfil your needs

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());
    }
}

I hope it can be useful to you

UPDATE

If you want to get the message provided by your resource bundle, you need a registered messageSource instance (It must be called messageSource)

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames" value="ValidationMessages"/>
</bean>

Inject your MessageSource instance inside your View

@Autowired
private MessageSource messageSource;

And to get your message, do as follows

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);
    }
}

Your Validator should looks like

/**
  * 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);
゛时过境迁 2024-09-06 20:45:29

我最近遇到了这个问题,找到了一个更简单的方法(也许是Spring 3的支持)

    List<FieldError> errors = bindingResult.getFieldErrors();
    for (FieldError error : errors ) {
        System.out.println (error.getObjectName() + " - " + error.getDefaultMessage());
    }

不需要更改/添加消息源。

I met this problem recently, and found an easier way (maybe it's the support of Spring 3)

    List<FieldError> errors = bindingResult.getFieldErrors();
    for (FieldError error : errors ) {
        System.out.println (error.getObjectName() + " - " + error.getDefaultMessage());
    }

There's no need to change/add the message source.

愁杀 2024-09-06 20:45:29

使用 Java 8 流

bindingResult
.getFieldErrors()
.stream()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));

With Java 8 Streams

bindingResult
.getFieldErrors()
.stream()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));
顾挽 2024-09-06 20:45:29

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 此处

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));
}

NOTE: Calling Errors.getDefaultMessage() will not necessarily return the same message that is generated from the code + args. The defaultMessage is a separate value defined when calling the Errors.rejectValue() method. See Errors.rejectValue() API Here

旧人九事 2024-09-06 20:45:29

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 />");
}

WebMvcConfigurerAdapter:

@Bean(name = "messageSourceAccessor")
public org.springframework.context.support.MessageSourceAccessor messageSourceAccessor() {
    return new MessageSourceAccessor( messageSource());
}

Controller:

@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 />");
}
悲喜皆因你 2024-09-06 20:45:29

获取与每个字段关联的所有错误的 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

获取与每个字段关联的错误合并在一起作为单个 StringMap >:

@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

To obtain a Map of all the errors associated with each field:

@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

To obtain a Map with the errors associated with each field merged together as a single 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文