Java 从servlet设置错误消息和正文

Java 从servlet设置错误消息和正文,java,servlets,httpresponse,Java,Servlets,Httpresponse,我想编写一个servlet,返回http响应,如下所示: HTTP/1.1 500 <short custom message> Content-Length: ... <longer custom message> HTTP/1.1500 内容长度:。。。 原因是,我希望编程客户端能够处理响应消息以获取特定响应,但我还希望在响应正文中填充更长的解释,以便使用浏览器轻松访问 现在,HttpServletResponse有一个sendError(int,String)

我想编写一个servlet,返回http响应,如下所示:

HTTP/1.1 500 <short custom message>
Content-Length: ...

<longer custom message>
HTTP/1.1500
内容长度:。。。
原因是,我希望编程客户端能够处理响应消息以获取特定响应,但我还希望在响应正文中填充更长的解释,以便使用浏览器轻松访问

现在,HttpServletResponse有一个sendError(int,String)方法,允许我指定错误代码和消息。javadocs只说消息将嵌入某种html页面中,但没有说明如何设置http响应消息。调用此方法后,不允许在响应中写入任何其他内容。在我的测试(使用jetty)中,消息用于http响应和html正文,这对我来说很好,只是我想指定两个不同的字符串,并且我不认为http响应消息的设置可以用不同的实现来保证

还有一个setStatus(int)方法,您可以用任何代码调用它,然后您可以编写自己的html正文。这很接近,只是您不能指定http响应消息

最后,还有一个setStatus(int,String)方法,它实际上完全满足我的要求,但是由于某种模糊性,它被弃用了。我假设一些servlet容器正在将消息写入响应主体并关闭响应

response.getWriter().print(message);
response.setStatus(500);

除了使用不推荐的方法外,我假设我在这里被搞砸了,但我很好奇是否有其他人知道任何窍门?

您可以通过在web.xml中指定特定于错误的页面来自定义错误页面:

<error-page>
  <error-code>500</error-code>
  <location>/error500.jsp</location>
</error-page>

500
/error500.jsp
在jsp文件中,您可以使用请求属性来显示自定义消息和其他信息

还有一个setStatus(int)方法,您可以用任何代码调用它,然后您可以编写自己的html正文。这很接近,只是您不能指定http响应消息

您有没有理由不使用
response.setStatus(500)
设置HTTP状态码,然后写入响应的输出流

这就是如何在最低级别上实现“向响应体写入”

下面是一个例子:

public class ErrorServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        // 500 error
        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        resp.getWriter().print("<html><head><title>Oops an error happened!</title></head>");
        resp.getWriter().print("<body>Something bad happened uh-oh!</body>");
        resp.getWriter().println("</html>");
    }
}
public类ErrorServlet扩展了HttpServlet{
@凌驾
受保护的无效服务(HttpServletRequest-req、HttpServletResponse-resp)
抛出ServletException、IOException{
//500错误
响应设置状态(HttpServletResponse.SC_内部_服务器_错误);
resp.getWriter().print(“哦,发生了一个错误!”);
resp.getWriter().print(“发生了不好的事情啊哦!”);
resp.getWriter()println(“”);
}
}
web.xml:

<web-app>
    <servlet>
        <servlet-name>myerror</servlet-name>
        <servlet-class>brown.testservlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myerror</servlet-name>
        <url-pattern>/myErrorPage</url-pattern>
    </servlet-mapping>
</web-app>

迈罗
brown.testservlet.ErrorServlet
迈罗
/myErrorPage
以及输出:

$ curl -I http://localhost:8080/testservlet/myErrorPage  
HTTP/1.1 500 Internal Server Error  
Content-Length: 108  
Server: Jetty(6.1.16)  

$ curl -v http://localhost:8080/testservlet/myErrorPage
* About to connect() to localhost port 8080 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /testservlet/myErrorPage HTTP/1.1
> User-Agent: curl/7.20.0 (i686-pc-mingw32) libcurl/7.20.0 OpenSSL/0.9.8k zlib/1.2.3
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Content-Length: 108
< Server: Jetty(6.1.16)
<
<html><head><title>Oops an error happened!</title></head><body>Something bad happened uh-oh!</body></html>
* Connection #0 to host localhost left intact
* Closing connection #0
$curl-Ihttp://localhost:8080/testservlet/myErrorPage  
HTTP/1.1500内部服务器错误
内容长度:108
服务器:Jetty(6.1.16)
$curl-vhttp://localhost:8080/testservlet/myErrorPage
*即将连接()到本地主机端口8080(#0)
*正在尝试127.0.0.1。。。有联系的
*已连接到本地主机(127.0.0.1)端口8080(#0)
>GET/testservlet/myErrorPage HTTP/1.1
>用户代理:curl/7.20.0(i686-pc-mingw32)libcurl/7.20.0 OpenSSL/0.9.8k zlib/1.2.3
>主机:本地主机:8080
>接受:*/*
>
如果您想在标题中显示自定义错误消息,为什么不使用
响应添加您自己的标题。addHeader(String,String)
?将这一点与matt b的答案结合起来可以完成这项工作。

好吧,对不起,为错误响应设置正文的最明显原因是,当错误发生时,在浏览器中显示一些人类可读的内容。这就是为什么生成HTML是Servlet规范中sendError的默认行为的原因


在我的例子中,我想要一些不同的东西,因为我正在创建web服务,如果一切正常,这个具体的服务不会返回响应。

使用JBoss 6,我得出结论,在调用getWriter禁用JBoss自定义错误页响应后,必须设置响应代码。我猜,根据响应的状态,实现提供了不同的编写器

response.getWriter().print(message);
response.setStatus(500);

似乎所有设计用于在HTTP中设置原因短语的API都因为以下原因而过时:

RFC 7230,超文本传输协议(HTTP/1.1):消息语法和路由,2014年6月:

原因短语元素存在的唯一目的是提供 与数字状态代码关联的文本描述, 主要是出于对早期互联网应用协议的尊重 交互文本客户端更频繁地使用A 客户端应忽略原因短语内容


Tomcat删除了对org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER属性的支持

谢谢,这是一个很好的观点,可能会帮助大多数人解决这个问题:)我碰巧使用的嵌入式jetty没有整个web应用程序设置:这是一个完全独立的servlet。我至少可以看看错误页面是否可以在代码中进行设置,但我可能会让编程调用方查看正文中的详细信息。我只是想提一下我遇到的一个警告。如果您尝试使用html页面而不是jsp,服务器将不会发送正确的状态代码,尽管会显示错误页面内容。是的,您引用的问题部分说明我理解此选项。它还指出,这不允许您设置http响应消息(示例中的“内部服务器错误”,即自动调用)