JavaServletAPI-如何在不提交响应的情况下设置响应状态和原因短语
我正在使用Tomcat和SpringWebMVC编写一个REST应用程序 我想使用HTTP状态码和一些XML负载向我的客户机发送错误信号,这些XML负载包含关于出错原因的更多信息 为了捕获所有错误,无论它们发生在何处,我编写了一个过滤器,用于包装响应并覆盖sendError方法:JavaServletAPI-如何在不提交响应的情况下设置响应状态和原因短语,java,tomcat,servlets,tomcat7,servlet-3.0,Java,Tomcat,Servlets,Tomcat7,Servlet 3.0,我正在使用Tomcat和SpringWebMVC编写一个REST应用程序 我想使用HTTP状态码和一些XML负载向我的客户机发送错误信号,这些XML负载包含关于出错原因的更多信息 为了捕获所有错误,无论它们发生在何处,我编写了一个过滤器,用于包装响应并覆盖sendError方法: private static final class GenericErrorResponseWrapper extends HttpServletResponseWrapper { @Override
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.setStatussc,msg已弃用。
Tomcat生成的HTTP响应头不正确,它以第一行HTTP/1.1500 OK开头。500是正确的,但原因短语应该是内部服务器错误,而不是OK。
我如何实现我的过滤器,使它做正确的事情,并没有弃用警告?Javadoc中命名的两个备选方案对我来说都不可用:
sendErrorsc,msg不可用,因为它提交了响应主体,我无法再编写XML负载
仅带有错误代码的setStatussc理论上是可用的,但它也会在响应头的第一行中创建硬编码的OK字符串。
不幸的是,没有办法避免弃用警告。正如您已经提到的,API文档中提到的两个备选方案并不包含相同的功能。当然,您可以使用@SuppressWarningDeprecation注释您的方法,以指示不推荐使用的方法的用途
另一方面,Tomcat不使用您的消息字符串(即使提供了消息字符串),这是一个配置问题。出于某种奇怪的原因,Tomcat默认情况下会忽略提供的消息字符串,并根据传递的返回代码使用默认错误消息。您必须将系统属性org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER设置为true,以强制Tomcat使用您提供的错误消息。有关这方面的更多详细信息,请参阅。很遗憾,没有办法避免弃用警告。正如您已经提到的,API文档中提到的两个备选方案并不包含相同的功能。当然,您可以使用@SuppressWarningDeprecation注释您的方法,以指示不推荐使用的方法的用途
另一方面,Tomcat不使用您的消息字符串(即使提供了消息字符串),这是一个配置问题。出于某种奇怪的原因,Tomcat默认情况下会忽略提供的消息字符串,并根据传递的返回代码使用默认错误消息。您必须将系统属性org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER设置为true,以强制Tomcat使用您提供的错误消息。有关此问题的更多详细信息,请参见。作为备选答案-您可以先编写XML有效负载,而不调用flush/flushBuffer,并且只有在编写完之后,才可以执行sendErrorint,String,这将刷新缓冲区。作为备选答案-您可以先编写XML有效负载,而不调用flush/flushBuffer,然后再执行sendErrorint、String,这将刷新缓冲区。javadoc解释了为什么不推荐使用该方法,以及应该使用哪种方法。阅读它。不幸的是,这对我没有帮助,因为我想编写自己的响应XML负载,而不是默认的tomcat HTML错误页。@JB Nizet:您应该阅读Javadoc。setStatusint sc、String msg没有替代品,具有相同的功能。@jarnbo您应该自己阅读。我引用:从版本2.1开始,由于消息参数的含义不明确。要设置状态代码,请使用setStatusint;要发送带有说明的错误,请使用sendErrorint,String。设置此响应的状态代码和消息。@EJP:这两种方法中的哪一种符合Bastian的要求?他甚至在他的问题中解释了为什么建议的替换方法都不合适。javadoc解释了为什么该方法被弃用,以及应该使用哪种方法。阅读它。不幸的是,这对我没有帮助,因为我想编写自己的响应XML负载,而不是默认的tomcat HTML错误页。@JB Nizet:您应该阅读Javadoc。setStatusint sc、String msg没有替代品,具有相同的功能。@jarnbo您应该自己阅读。我引用:从版本2.1开始,由于消息参数的含义不明确。要设置状态代码,请使用setStatusint;要发送带有说明的错误,请使用sendErrorint,String。设置此响应的状态代码和消息。@EJP:这两种方法中的哪一种符合Bastian的要求?他甚至在问题中解释了为什么建议的替代方法都不合适。