25

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

我想知道如何实现我的方法,所以如果一切正常(在响应的正文中)它们会返回 JSON,或者抛出一个 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";
    }
}

或者更确切地说是这样:

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

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

4

5 回答 5

31

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

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

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

于 2013-04-30T10:16:38.330 回答
16

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

当出现问题时,您只需设置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;
    }
}

资源被序列化,结果是

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

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

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

于 2013-04-30T08:40:45.803 回答
8

您可以使用@ExceptionHandler检查@ControllerAdvice链接

于 2013-05-01T06:24:38.020 回答
0

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

您可以尝试以下代码:

@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)); 
}
于 2013-08-27T08:35:37.770 回答
0

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

图书馆有现成的:

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

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

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

于 2017-08-24T15:29:01.950 回答