简体   繁体   English

如何从Spring MVC控制器返回错误状态和验证错误?

[英]How to return error status and validation errors from this Spring MVC controller?

I have an action method defined like this in one of my controllers: 我在我的一个控制器中有一个这样定义的动作方法:

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Post create(@Valid Post post, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        // how to return an error status + error messages from here?
    } else {
        postRepository.persist(post);
        return post;
    }
}

When the post is persisted successfully, I return the post back to the client. 当帖子成功保留后,我将帖子返回给客户端。 But when it has validation errors, I want to return an Error status code as well as all the validation error messages back to the client. 但是当它有验证错误时,我想将错误状态代码以及所有验证错误消息返回给客户端。

What's the best way to do this? 最好的方法是什么?

Sine you are desigining a REST api, you need to create your own Pojo (aka. Resource) which will represent odd behaviour or validation errors, as stated by horaceman. 正如您所设计的那样,您需要创建自己的Pojo(aka。资源),这将代表奇怪的行为或验证错误,正如horaceman所述。 I will show you how we do it in our application. 我将在我们的应用程序中向您展示我们是如何做到的。

Since we are using JSON as a data representation, we wish to receive following information if unexpected exception occurs. 由于我们使用JSON作为数据表示,因此如果发生意外异常,我们希望收到以下信息。

{ "status" : "EXCEPTION", "exceptionName" : "MyCustomException", "exceptionMsg" : "ex.unsupportedOperation" }

This is an example of course. 这是一个例子。 Nice solution about it is that we can treat exceptionMsg as a key in our frontend to display proper i18n message or display it to the user as it is (in this case we use more descriptive messages). 关于它的一个很好的解决方案是我们可以将exceptionMsg视为我们前端的一个键,以显示正确的i18n消息或将其显示给用户(在这种情况下,我们使用更多的描述性消息)。

Now, when everything is OK we do something like this: 现在,当一切正常时,我们会这样做:

{ "status" : "OK", "data" : {(...)} }

Data element is optional. Data元素是可选的。 We can send whatever we need to notify the frontend, or skip it totally. 我们可以发送任何我们需要通知前端的内容,或完全跳过它。

The last scenario would be yours - validation errors. 最后一个场景是你的 - 验证错误。 In this case we usually send following content: 在这种情况下,我们通常发送以下内容:

{ "status" : "VALIDATION_FAILED", "errors" : [ "fieldName" : "username", "errorCode" : "validation.requiredField", "errorMsg" : "Username is required."] }

So clearly API clients will receive information that validation has failed and in proper fields - exact details about what went wrong. 很明显,API客户端将收到验证失败的信息,并在适当的字段中显示错误的详细信息。 Of course errors is an array (or List ), so we always provide as many details as necessary. 当然errors是一个数组(或List ),因此我们总是根据需要提供尽可能多的细节。

How I do it? 我是怎么做到的 Easy, those objects are simple POJOS which are translated to JSON using Jackson. 很简单,那些对象是简单的POJOS,使用Jackson翻译成JSON。 This gives me unlimited possibilities of JSON representation. 这给了我无限的JSON表示可能性。 What I do, is I'm preparing POJO representing Validation errors (for instance) and add it as a Model to my ModelAndView instance. 我做的是,我正在准备表示验证错误的POJO(例如)并将其作为Model添加到我的ModelAndView实例中。 Then I just rely on Spring to do proper JSON marshaling. 然后我只依靠Spring来做适当的JSON编组。

In your case you have @ResponseBody annotation with your Post instance, so as far as I know you won't be able to do that. 在你的情况下,你的Post实例有@ResponseBody注释,所以据我所知你将无法做到这一点。 Your setup is saying "Well, no matter what happens - always return an instance of Post". 你的设置是说“好吧,不管发生了什么 - 总是返回一个Post的实例”。 What you should do, is to replace it with simple ModelAndView , supply it with proper Model based on validation and return it to the client API. 你应该做的是用简单的ModelAndView替换它,根据验证为它提供适当的Model并将其返回给客户端API。

For @ResponseBody I would remove BindigResult from the method signature and let the BindException be thrown. 对于@ResponseBody,我会从方法签名中删除BindigResult并抛出BindException。 I would then use an @ExceptionHandler method to return an object that contains the errors as Likacz described. 然后,我将使用@ExceptionHandler方法返回包含Likacz描述的错误的对象。

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Post create(@Valid Post post) {
    postRepository.persist(post);
    return post;
}

@ExceptionHandler
public ValidationErrors handleException(BindException ex) {
  // ...
}

i think you want to make an ajax call in your controller. 我想你想在你的控制器中进行ajax调用。 you return a post object in the method, so it is impossible to return another object(such as error message with code). 您在方法中返回一个post对象,因此无法返回另一个对象(例如带代码的错误消息)。 how about return an ExecutionResult instead? 如何返回ExecutionResult呢?

ExecutionResult{
 private int statusCode;
 private String message;
 private Object yourPost;
 //get and set methods here...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM