Java 带有错误处理的 Spring MVC Rest 服务控制器做得对吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16295184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:11:53  来源:igfitidea点击:

Spring MVC Rest Service Controller with Error Handling done right?

javaspringrestspring-mvc

提问by pascalwhoop

I was wondering how to correctly implement a Spring Controller which is supposed to serve as a REST Service. Especially I want to try and make the interface as RESTful as possible. Also i'd like to make use of HTTP Error codes so my Clients can act accordingly.

我想知道如何正确实现一个应该作为 REST 服务的 Spring 控制器。特别是我想尝试使界面尽可能 RESTful。此外,我想使用 HTTP 错误代码,以便我的客户可以采取相应的行动。

I was wondering how to implement my Methods, so they return JSON if everything works fine(in the body of the response) or toss a http error code as well as a custom reason why it didnt work(maybe errors that came from the DAO or the database). However I'm not sure which one is the right way? return a String and add the values to return to a Model, or return a HashMap and put my stuff in there? or return the objects directly? but then what if an error occures and i cannot return said Class? return null instead? I post 2-3 ways of doing it that i could imagine:

我想知道如何实现我的方法,所以如果一切正常(在响应的正文中)或抛出一个 http 错误代码以及它不起作用的自定义原因(可能来自 DAO 的错误或数据库)。但是我不确定哪个是正确的方法?返回一个字符串并添加值以返回到模型,或者返回一个 HashMap 并将我的东西放在那里?还是直接返回对象?但是如果发生错误并且我无法返回所述类怎么办?而是返回 null?我发布了我可以想象的 2-3 种方法:

@RequestMapping(value="/addUser", method= RequestMethod.POST)
public String addUser(@RequestBody User user, HttpServletResponse response, Model model) throws Exception{

    try{
        userService.addUser(user);
        model.addAttribute("user", userService.getUser(user.getUsername(), user.getPassword()));
        return "user";
    }catch(Exception e){
        model.addAttribute("error", e.toString());
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
        return "error";
    }
}

Or rather this way:

或者更确切地说是这样:

@RequestMapping(value="/addUser", method= RequestMethod.POST)
public @ResponseBody Map addUser(@RequestBody User user, HttpServletResponse response){
    Map map = new HashMap();
    try{
        userService.addUser(user);
        map.put("success", true);
        map.put("username", user.getUsername());
    }catch (KeyAlreadyExistsException e){
        map.put("success", false);
        map.put("Error", e.toString());
        response.sendError(HttpServletResponse.SC_FORBIDDEN, e.toString());
    }catch(Exception e){
        map.put("success", false);
        map.put("Error", e.toString());
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
    }
    finally {
        return map;
    }
}

I realize code is not "just right" but i cannot figure out how to make it the way it needs to be. Maybe some experiences responses would help? Thx for the support already

我意识到代码不是“恰到好处”,但我不知道如何使它成为它需要的方式。也许一些经验的回应会有所帮助?谢谢你的支持

采纳答案by marco.eig

You could also catch your exceptions with @ExceptionHandlerannotated methos within your Rest Controller.

您还可以@ExceptionHandler在 Rest Controller 中使用带注释的方法捕获异常。

@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleException(Exception e) {
    return "return error object instead";
}

this will make your acutal controller/business logic cleaner.

这将使您的实际控制器/业务逻辑更清晰。

回答by Bart

Firstly, I think you should always return a object when returning JSON. Even when something goes horribly wrong.

首先,我认为在返回 JSON 时应该始终返回一个对象。即使发生了可怕的错误。

When something goes wrong you simply set response.setStatus()and return a resource describing the error.

当出现问题时,您只需设置response.setStatus()并返回一个描述错误的资源。

public class ErrorResource implements Resource {
    private final int status;
    private final String message;

    public ErrorResource(int s, String m) {
        status = s;
        message = m;
    }

    public int getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }
}

The resource gets serialized and the outcome would be

资源被序列化,结果将是

{"status":500, "message":"Yay!"}

Using a Mapwill work but I would like to advise you to write some resource classes which define the object to be returned. They would be easier to maintain. Mapsdon't offer any structure while structure is a very important part when creating a REST service.

使用 aMap会起作用,但我建议您编写一些定义要返回的对象的资源类。它们会更容易维护。Maps不提供任何结构,而结构是创建 REST 服务时非常重要的部分。

I don't think you should return a resource with the raw exception message embedded. It can potentially leak information you don't want anyone to see.

我认为您不应该返回嵌入了原始异常消息的资源。它可能会泄露您不希望任何人看到的信息。

回答by Bassem Reda Zohdy

you can use @ExceptionHandlerwith @ControllerAdvicecheck this link

你可以用@ExceptionHandler@ControllerAdvice检查此链接

回答by agus w

use ResponseEntity class to exploit error with http status code.

使用 ResponseEntity 类利用 http 状态代码来利用错误。

You could try the following code:

你可以试试下面的代码:

@RequestMapping(value = "/profile", method = RequestMethod.GET) 
@ResponseBody @ResponseStatus(value = HttpStatus.OK) 

public ResponseEntity<UserVO> getUserProfile() 
{ 
   string userName = getUserAuthentication().getName(); 
   if (StringUtils.isEmpty(userName)) RestUtil.defaultJsonResponse(""); 
   User user = userService.getUserByUserNameWithCounters(userName); 
   return RestUtil.getJsonResponse(new UserVO(user)); 
}

回答by zg2pro

If you want your whole Exception with stackTrace to be transmitted toward your client, as @Bart said you should send an "ErrorResource" object.

如果您希望将带有 stackTrace 的整个异常传输到您的客户端,正如@Bart 所说,您应该发送一个“ErrorResource”对象。

A library has it off-the-shelf :

图书馆有现成的:

<dependency>
  <groupId>com.github.zg2pro</groupId>
  <artifactId>spring-rest-basis</artifactId>
  <version>0.2</version>
</dependency>

add it to your project and then just add a "@ControllerAdvice" class to your beans, as it is explained in the project wiki.

将它添加到您的项目中,然后将“@ControllerAdvice”类添加到您的 bean,如项目 wiki 中所述

That should handle your errors nicely!

那应该可以很好地处理您的错误!