Java Servlet API - 如何在不提交响应的情况下设置响应状态和原因短语

时间:2013-11-22 08:38:40

标签: java tomcat servlets tomcat7 servlet-3.0

我正在使用Tomcat和Spring WebMVC编写REST应用程序。

我想使用HTTP状态代码向我的客户端发送错误信号以及一些包含有关错误信息的XML有效负载。

要捕获所有错误而不管它们出现在何处,我编写了一个包含响应并覆盖sendError()方法的Filter:

private static final class GenericErrorResponseWrapper 
extends HttpServletResponseWrapper   
{
  @Override
  public void sendError(int sc, String msg) throws IOException {
    final HttpServletResponse wrappedResponse = (HttpServletResponse) getResponse();
    wrappedResponse.setStatus(sc, msg);
    wrappedResponse.setContentType("application/xml");
    PrintWriter writer = wrappedResponse.getWriter();
    try {
      SimpleXmlWriter xmlWriter = SimpleXmlWriterWrapper.newInstance(writer);
      xmlWriter.writeStartElement("ns2", "genericError")
      .writeAttribute("xmlns:ns2", "http://mynamespace")
      .writeCharacters(msg)
      .writeEndDocument().flush();
      writer.flush();
      wrappedResponse.flushBuffer();
    } finally {
      writer.close();
    }
  }
}

这个实现有两个问题:

  1. 它在Eclipse中生成弃用警告,因为不推荐使用HttpServletResponse.setStatus(sc,msg)。
  2. Tomcat生成的HTTP响应标头不正确,它从第一行“HTTP / 1.1 500 OK”开始。 500是正确的,但不是OK,原因短语应该是“内部服务器错误”。
  3. 如何实施我的过滤器以使其做正确的事情并且没有弃用警告?在Javadoc中命名的两个替代方案都不适用于我:

    • sendError(sc,msg)不可用,因为它提交响应正文并且我不能再写XML有效负载了
    • setStatus(sc)只有错误代码在理论上可用,但它也在响应头的第一行创建了硬编码的“OK”字符串。

2 个答案:

答案 0 :(得分:4)

遗憾的是,无法避免弃用警告。正如您自己提到的那样,API文档中提到的两个替代方案并未涵盖相同的功能。您当然可以使用@SuppressWarnings("deprecation")注释您的方法,以表明不推荐使用已弃用的方法。

另一方面,Tomcat不使用您的消息字符串,即使提供了消息字符串,也是一个配置问题。出于某些奇怪的原因,Tomcat将默认忽略提供的消息字符串,并使用基于传递的返回代码的默认错误消息。您必须将系统属性org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER设置为true,以强制Tomcat使用您提供的错误消息。有关详细信息,请参阅Tomcat documentation

答案 1 :(得分:0)

作为另一种选择 - 您可以先编写XML有效负载,而不必调用flush / flushBuffer,然后只执行sendError(int, String),这将刷新缓冲区。