2013-04-30 17 views
24

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

我想知道如何实现我的方法,所以他们返回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; 
    } 
} 

我知道代码是不是“刚刚好”,但我无法弄清楚如何让它成为它需要的方式。也许一些经验反应会有所帮助? Thx的支持已经

回答

28

您也可以在您的Rest Controller中使用@ExceptionHandler带注释的方法来捕捉您的例外情况。

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

这将使您的acutal控制器/业务逻辑更清洁。

+0

我喜欢这个主意,我其实只是这么做的!我按照Bart的建议创建了一个错误资源,然后在这个方法中处理ctrl中的所有错误。我可能会进一步推广和处理广泛的错误应用,但一次只能一步。 – pascalwhoop 2013-04-30 10:31:20

+0

您可以在您的Controller中为每个异常类型创建多个ExceptionHandlers。 – 2013-04-30 11:03:17

+2

我发现它看起来更清洁,如果我只是每个控制器有一个exceptionhandler方法而不是整个数组,然后照顾检查这个处理程序中引发的错误 – pascalwhoop 2013-04-30 12:33:31

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!"} 

使用Map工作,但我想提醒你写它定义了对象返回一些资源类。他们会更容易维护。 Maps不提供任何结构,而在创建REST服务时,结构是非常重要的部分。

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

+0

所以你会说我有一个主要的类“returnRessource”从中我打算返回所有其他类,无论错误或实际值应继承?否则,我真的不明白你打算如何通过如果你有一个方法让我们说'public User getUser(){...}'它打击了,你不能只返回你必须返回用户类的另一个类。或者你认为它应该是'public Object getUser(){...}'? – pascalwhoop 2013-04-30 09:33:49

+0

我也许应该补充一点,我打算使用Angular编写我的端点。这里根据http响应代码很方便。但我仍然同意,一个json对象比默认的tomcat错误页面更好。如何返回一个对象,而不是response.sendError方法?我的意思是,虽然仍然有HTTP错误代码集 – pascalwhoop 2013-04-30 09:46:17

+0

response.setStatus(statusCode)是否有窍门;-) – 2013-04-30 10:09:29

8

可以使用@ExceptionHandler@ControllerAdvice检查这个link

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

添加更多解释。 – Max 2013-08-27 08:56:11

+0

对不起,我没有格式化,但试试这个代码 - >'@RequestMapping(value =“/ profile”,method = RequestMethod.GET) @ResponseBody @ResponseStatus(value = HttpStatus.OK) public ResponseEntity getUserProfile(){ \t String userName = getUserAuthentication()。getName(); \t \t if(StringUtils.isEmpty(userName)) \t \t RestUtil.defaultJsonResponse(“”); \t \t User user = userService.getUserByUserNameWithCounters(userName); \t \t return RestUtil.getJsonResponse(new UserVO(user)); }' – 2013-09-03 06:13:24

0

如果你希望你与堆栈跟踪整个异常向客户传送,如@Bart说你应该发送“ErrorResource”对象。

库有它关闭的,现成的:

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

把它添加到您的项目,然后只需添加一个“@ControllerAdvice”类的豆,因为它是在project wiki解释。

这应该很好地处理你的错误!