我正在使用 Tomcat 和 Spring WebMVC 编写一个 REST 应用程序。
我想使用 HTTP 状态代码和一些 XML 有效载荷向我的客户端发出错误信号,其中包含有关错误原因的更多信息。
为了捕获所有错误,无论它们发生在何处,我编写了一个过滤器来包装响应并覆盖 sendError() 方法:
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();
}
}
}
这个实现有两个问题:
- 它在 Eclipse 中生成弃用警告,因为 HttpServletResponse.setStatus(sc, msg) 已弃用。
- Tomcat 生成的 HTTP 响应 header 不正确,它以第一行“HTTP/1.1 500 OK”开头。 500 是正确的,但原因短语应该是“内部服务器错误”而不是 OK。
我怎样才能实现我的过滤器,以便它做正确的事情并且没有弃用警告? Javadoc 中命名的两个备选方案对我来说都不可用:
- sendError(sc, msg) 不可用,因为它提交了响应主体,我不能再编写 XML 有效负载
- 仅包含错误代码的 setStatus(sc) 在理论上是可用的,但它还会在响应 header 的第一行中创建硬编码的“OK”字符串。
最佳答案
不幸的是,没有办法避免弃用警告。正如您自己提到的,API 文档中提到的两个备选方案并不涵盖相同的功能。当然,您可以使用 @SuppressWarnings("deprecation")
注释您的方法,以表明打算使用已弃用的方法。
另一件事是 Tomcat 不使用您的消息字符串,即使提供了消息字符串也是配置问题。由于某些奇怪的原因,Tomcat 默认会忽略提供的消息字符串,并使用基于传递的返回码的默认错误消息。您必须将系统属性 org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER
设置为 true
以强制 Tomcat 使用您提供的错误消息。有关这方面的更多详细信息,请参阅 Tomcat documentation .
关于Java Servlet API - 如何在不提交响应的情况下设置响应状态和原因短语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20140376/