从Spring控制器或服务返回错误和消息

时间:2011-04-22 17:02:19

标签: spring-mvc exception-handling

我正在使用Spring MVC将一些servlet迁移到Spring框架。目前在每个servlet中我们对用户进行身份验证,如果身份验证失败,我们会这样做:

if (authfailed)
{
  response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                     "You are not authorized.");
  return;
}

在前端是基于YUI的应用程序,当返回错误状态时,“失败”回调会显示一个对话框,其中显示上面给出的错误消息。

我知道在我的控制器中我可以获得响应对象并调用sendError,但这是处理此问题的最佳方法吗? sendError也抛出一个IOException,所以我必须抓住它 - 在每个控制器的每个方法中插入一些恼人的代码。

我在处理异常时遇到同样的问题 - servlet具有在catch方法中调用sendError的try-catch块。我知道我可以使用

标记我的异常处理程序
@ExceptionHandler
@ResponseStatus(value = HttpStatus.NOT_FOUND)

但是异常处理类不需要在每个控制器类中吗?

最后,如果在从控制器调用的服务中发生异常,异常是否会冒泡到控制器或我应该处理服务中的异常(从而将这些异常处理问题推送到服务层)?

这似乎比它应该更难,但正如Spring中的许多事情一样,我可能不明白发生了什么。我想要做的就是在响应中发送错误状态和消息!

谢谢,

1 个答案:

答案 0 :(得分:16)

看起来你的问题本身就有大部分答案:)

重申一下,

让控制器像这样

@RequestMapping("/test") 
public String verifyAuth(HttpServletRequest request) throws NotFoundException {
    String id = request.getParameter("id");

    if (id == null) 
        throw new NotFoundException("Id not found in the request");

    return "success";
}

在NotFoundException.java中声明异常类,

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Id Not Found")
public class NotFoundException extends Exception {

    public NotFoundException(String msg) {
        super(msg);
    }
}

此异常类不必是每个控制器类。将其声明为公共类,并将其导入每个必需的控制器。

这是一种做法。如果您喜欢非spring类型,请在每个控制器参数中声明HttpServletResponse并执行

@RequestMapping("/test") 
public String verifyAuth(HttpServletRequest request, HttpServletResponse response) {
   ...
   try {
    response.sendError(..)
   catch(..) {}
}

或者您可以使用视图来显示错误消息,

@RequestMapping("/test") 
public String verifyAuth(HttpServletRequest request, Map<String, Object> map){
    String id = request.getParameter("id");

    if (id == null)  {
        map.put("status", HttpStatus.NOTFOUND);
        map.put("reason", "Id Not Found");

        return "error"
     }
      return "success";
}

确保你的viewResolver配置正确,并在error.jsp中获取错误字符串,你可以说。

<body>
${status} ${reason}
</body>

使用nice css定义error.jsp,以应对您期望的所有类型的错误。 这些不是唯一的方法。春天,你可以自由地做任何事情。我见过几个ppl渲染json对象的错误消息。

回答另一个问题,即控制器调用的服务中是否发生错误取决于您的方案。例如,您正在尝试读取用户存储,如果用户存储不可用错误发生,我会在那里处理从另一个副本用户存储中读取一个可用而如果我发现用户不存在我会将异常留给控制器扔。