返回Http状态代码

时间:2015-10-07 20:00:43

标签: java

我发现another post显示了我们如何创建自己的已检查异常,这些异常也返回不同于500的HTTP状态代码。但是,我需要它为RuntimeException。 然后,我发现WebApplicationException是一个未经检查的异常,返回HTTP状态代码,但不允许我像常规异常中那样设置消息。

Java EE 6中是否存在任何未经检查的异常,允许我像常规异常一样设置错误消息并返回我可以设置的HTTP状态代码?

编辑:根据约翰的要求,包括我为什么要这样做的解释。

我创建了一个过滤器来捕获来自我的请求参数的HTML和XSS攻击。我没有在Filter.doFilter中每次都检查那个太慢的问题,而是扩展HttpServletRequestWrapper并像这样使用它。

HttpFilterRequest implements Filter
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(new SafeHttpRequest((HttpServletRequest) request), response);
    } catch (SecurityViolationException e) {
        log.warn(format("A security violation was detected. Please enable debug for further details: %s]", e.getMessage()));
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.sendError(e.getStatusCode());
    }response);
  }

SafeHttpRequest extends HttpServletRequestWrapper (supressing parts to shorten code)
  @Override
  public String getParameter(String parameter) {
      return xssAndHtmlValidation(super.getParameter(parameter));
  }
  @Override
  public String getHeader(String name) {
      return xssAndHtmlValidation(super.getHeader(name));
  }

xssAndHtmlValidation()抛出SecurityViolationException这是RuntimeException,但catch的{​​{1}}块不起作用,因为我的异常被抛出为{{1}包含doFilter

1 个答案:

答案 0 :(得分:3)

好的,问题是您希望SafeHttpRequest.xssAndHtmlValidation()抛出一个可以传递出HttpServletRequest.getParameter()HttpServletRequest.getHeader()的异常,这两个异常都不会声明任何已检查的异常。您希望此异常最终由HttpFilterRequest.doFilter()捕获。您希望它具有可自定义的消息,并且您希望它携带HTTP响应代码。

你显然需要一个未经检查的例外来以这种方式解决问题。通过扩展java.lang.RuntimeException,从头开始创建一个新的似乎是最合适的。您可以为该类提供所需的任何字段,构造函数和方法,以便将任何信息从xssAndHtmlValidation()传输到过滤器。对异常类这样做对于任何其他类都没有什么不同,尽管您的构造函数应该确保调用适当的超类构造函数。

然后,过滤器必须具有用于新自定义异常类型的catch块。由于它是您自己的自定义异常,因此不太可能被请求和过滤器之间的任何内容捕获,并且由于您将捕获该特定异常,因此您可以轻松调用您为自己提供的任何好方法,例如可能{{{ 1}}。据推测,catch块会调用响应对象上的getResponseCode()方法之一,然后正常返回,而不是在堆栈中抛出异常。

顺便说一下,请注意,如果问题检测得太晚,在底层资源已经提交给其他响应后,尝试sendError()将导致sendError()而不是更改响应代码。客户端不会看到(因为,响应已经提交),但响应可能会被截断。

另请注意,目前还不清楚您是否确实需要自定义异常来携带HTTP响应代码。它会从一个实例变化到另一个实例吗?如果没有,那么适当的响应代码是完全抛出异常的事实,并且过滤器可以仅根据它捕获该特定异常类型的事实来适当地设置响应代码。

<强>更新

当然,如果您的JSP引擎要包装您的异常并将其作为IllegalStateException抛出,那么您可以捕获该异常并根据ServletException决定该做什么(但请注意原因是exception.getCause().getClass())。如果引擎在这种情况下尚未提交响应,那么这可能有效。

如果您的JSP引擎毕竟要拦截所有异常并将它们转换为HTTP代码500响应,那么基于抛出异常的任何方法都只是一个死胡同。然后,您最好的选择是在前端,过滤器中处理它,然后将请求传递到链中。这非常适合过滤器。

您担心在过滤器中进行测试会太慢,但只有当请求包含从未被下游组件检查的参数或标头时,这可能比您建议的替代方案慢。另一方面,如果请求标头或参数在每个下游被访问多次,那么基于请求包装器的方法实际上可能会更慢,因为您将在每次访问时执行验证,即使您只需要执行它每个参数/标题一次。