【问题标题】:Error Page Return a Status Code 200 default response错误页面返回状态码 200 默认响应
【发布时间】:2011-03-16 02:46:20
【问题描述】:

我们希望实施“fault barrier”策略来管理应用程序中的异常。我们的应用程序拥有的一件事是“回传”响应的概念,基本上是无操作,我们希望优先返回它而不是抛出 500、400 等 HTTP 状态代码 - 例如我们面向外部的应用程序应始终返回有效响应,即使引发了底层异常 - 我们希望在应用程序内部处理该异常,并仍返回有效的 noop 响应。

我们的第一个实现是一个 Servlet 过滤器,它将所有请求包装在一个 try/catch 块中,并从 catch 返回默认返回,例如:

try{
  chain.doFilter()
} catch (Throwable t) {
  generatePassbackResponse(HttpServletRequest req, HttpServletResponse res)
}

虽然这主要是可行的,而且感觉很好很干净(我们可以返回漂亮的文本,适当地设置内容/类型等),但一个问题似乎是,当抛出异常时,响应仍然通过 Status-代码:500。

HttpServletResponse.setStatus(200) 没有效果,javadoc 确实说它只适用于正常请求。

我们的第二个实现想法是我们可能必须转发到另一个页面,或者将 errorPage 插入 web.xml 并手动将错误发送到该页面 - 尽管我们对是否有人有具体建议感兴趣。

【问题讨论】:

    标签: java http exception servlets exception-handling


    【解决方案1】:

    有两种方法可以设置响应的 HTTP 状态:

    • setStatus() 只会设置状态
    • sendError() 将设置状态触发<error-page>机制

    sendError 的 Javadoc 表示,在调用 sendError 后应将响应视为已提交(这可以解释您的应用服务器的行为)。

    实现自定义 HttpServletResponseWrapper 将允许您强制执行您的行为 需要 sendError (并且可能将整个请求缓冲在内存中,以便您可以在通常提交请求之后发生的异常发送“回传”)。

    【讨论】:

      【解决方案2】:

      如果我没记错的话,如果您不希望其他任何东西来处理请求,则不应调用 chain.doFilter()。过滤器将在每种情况下都被执行,但 chain.doFilter() 将确保调用所有其他过滤器。为了正确阻止异常到达用户,您需要停止请求/响应处理。

      您也可以通过使用像 Spring 及其拦截器(就像过滤器一样)这样的框架来采取不同的路线。 Spring 为您提供了对拦截器以及如何处理响应的大量控制。当然,这对您的问题来说有点沉重。

      回复评论,据http://java.sun.com/products/servlet/Filters.html

      最重要的方法 过滤器接口是doFilter 方法...这种方法通常执行 以下一些操作:

      如果当前过滤器是最后一个 在以 目标 servlet,下一个实体是 链末端的资源; 否则,它是下一个过滤器 在 WAR 中配置。它调用 通过调用下一个实体 链对象上的 doFilter 方法 (传入请求和响应 它被称为或被包裹 它可能创建的版本)。 或者,它可以选择阻止 请求通过不调用 调用下一个实体。在后者 情况下,过滤器负责 填写回复。

      这个想法是这个“故障屏障”需要阻止所有其他过滤器执行,并以它认为必要的方式处理请求/响应。

      【讨论】:

      • Filter#doFilter() 方法中调用RequestDispatcher#forward()HttpServletResponse#sendRedirect() 之前不应调用FilterChain#doFilter()。这不是这里的情况。
      • 由于目标是捕获抛出的异常,但有一个通用过滤器,我们肯定需要调用 doFilter - 虽然这有点被搁置了,所以现在我们要看看是否abstract/dispatcher servlet 得到我们想要的。
      【解决方案3】:

      你能不能只使用标准的 web.xml 配置:

      <error-page>
          <error-code>500</error-code>
          <location>/error.jsp</location>
      </error-page>
      
      <error-page>
          <location>/error.jsp</location>
          <exception-type>java.lang.Exception</exception-type>
      </error-page>
      

      我看不出您还想做什么而这还不能满足?如果只是错误代码,那么我认为您可以使用响应对象进行设置。

      【讨论】:

      • 默认的错误页面处理程序(我们尝试过)似乎不允许我们覆盖状态代码。状态码是我们试图处理的重要部分,至少在 Glassfish 中,响应对象似乎不允许您在错误响应中设置状态码。由于这些是服务器到服务器的响应(在大多数情况下不是用户浏览器),因此状态代码对于 RESTful 响应可能非常重要。
      【解决方案4】:

      RESTEasy 框架允许您选择响应代码将使用 ExceptionMappers。可能是您不愿意使用它,但我发现它非常快速高效。

      涵盖 ExceptionMappers 的 JBoss 文档 http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html_single/index.html#ExceptionMappers

      我的博客文章展示了通用 RESTEasy 代码的 sn-p http://gary-rowe.com/agilestack/2010/08/22/my-current-development-stack/

      【讨论】:

      • 我不知道我是否会形容我们不愿意使用它,尽管在这种情况下考虑切换开发框架似乎有点矫枉过正。
      • 除非有令人信服的理由(因此“不愿意使用它”),否则我不会更改每个人都熟悉的开发框架,但可能是过渡相对轻松。跨度>
      猜你喜欢
      • 2015-05-12
      • 1970-01-01
      • 2012-07-31
      • 2015-10-13
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 2012-03-06
      相关资源
      最近更新 更多