Java 从 servlet 设置错误消息和正文
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3885725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting both error message and body from servlet
提问by Jeremy Huiskamp
I want to write a servlet that will return an http response like so:
我想编写一个 servlet,它将返回一个 http 响应,如下所示:
HTTP/1.1 500 <short custom message>
Content-Length: ...
<longer custom message>
The reason is that I want a programmatic client to be able to process the response message to take a particular response but I also want to fill in the response body with a longer explanation so that it's easy to hit using a browser.
原因是我希望程序化客户端能够处理响应消息以获取特定响应,但我还想用更长的解释填充响应正文,以便使用浏览器轻松点击。
Now, HttpServletResponse has a sendError(int, String) method that allows me to specify the error code and a message. The javadocs only say that the message will be embedded in some kind of html page, but nothing about setting the http response message. After calling this method, you are not allowed to write anything else to the response. In my tests (with jetty), the message is used both for the http response and an html body, which would be fine with me, except that I want to specify two different strings and I don't think the setting of the http response message is guaranteed with a different implementation.
现在, HttpServletResponse 有一个 sendError(int, String) 方法,允许我指定错误代码和消息。javadocs 只说消息将嵌入到某种 html 页面中,但没有设置 http 响应消息。调用此方法后,您不得在响应中写入任何其他内容。在我的测试中(使用 jetty),该消息同时用于 http 响应和 html 正文,这对我来说没问题,只是我想指定两个不同的字符串并且我不认为 http 响应的设置消息由不同的实现保证。
There's also a setStatus(int) method that you can call with any code, and then you can write your own html body. This is close, except that you can't specify the http response message.
还有一个 setStatus(int) 方法,你可以用任何代码调用它,然后你就可以编写自己的 html body。这很接近,只是您不能指定 http 响应消息。
Finally, there's a setStatus(int, String) method that actually does exactly what I want, but it's deprecated due to some kind of ambiguity. I'm assuming some servlet containers were writing the message to the response body and closing the response.
最后,有一个 setStatus(int, String) 方法,它实际上完全符合我的要求,但由于某种歧义,它已被弃用。我假设一些 servlet 容器正在将消息写入响应正文并关闭响应。
Aside from using the deprecated method, I'm assuming I'm screwed here, but I'm curious if anyone else knows any tricks?
除了使用已弃用的方法之外,我假设我在这里被搞砸了,但我很好奇是否有人知道任何技巧?
回答by FRotthowe
You can customize error pages by specifying error specific pages in web.xml:
您可以通过在 web.xml 中指定错误特定页面来自定义错误页面:
<error-page>
<error-code>500</error-code>
<location>/error500.jsp</location>
</error-page>
In the jsp file you can use request attributes to show a custom message and other info.
在 jsp 文件中,您可以使用请求属性来显示自定义消息和其他信息。
回答by matt b
There's also a setStatus(int) method that you can call with any code, and then you can write your own html body. This is close, except that you can't specify the http response message.
还有一个 setStatus(int) 方法,你可以用任何代码调用它,然后你就可以编写自己的 html body。这很接近,只是您不能指定 http 响应消息。
Is there any reason why you would not use response.setStatus(500)
to set the HTTP status code, followed by writing to the response's output stream?
是否有任何理由不使用response.setStatus(500)
设置 HTTP 状态代码,然后写入响应的输出流?
This is how "writing to the response body" is achieved at the lowest level.
这就是在最低级别实现“写入响应主体”的方式。
Here's an example:
下面是一个例子:
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>");
}
}
web.xml:
网页.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>
And the output:
和输出:
$ 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
回答by nash
If you want to have a custom error message in the headers why not add you own header with response.addHeader(String, String)
? Combining this with matt b's answer could do the job.
如果您想在标题中包含自定义错误消息,为什么不添加您自己的标题response.addHeader(String, String)
?将此与 matt b 的答案相结合可以完成这项工作。
回答by Juan
Well, sorry, the most obvious reason to have a body for an error response is to show something human-readable in a browser when an error happens. This is the reason why generating HTML is the default behaviour of sendError in the Servlet spec.
好吧,抱歉,为错误响应提供正文的最明显原因是在发生错误时在浏览器中显示一些人类可读的内容。这就是为什么生成 HTML 是 Servlet 规范中 sendError 的默认行为的原因。
In my case, I want something different, because I'm creating web services, and this concrete one does not return a response if everything works fine.
就我而言,我想要一些不同的东西,因为我正在创建 Web 服务,如果一切正常,这个具体的服务不会返回响应。
回答by Elijah
Using JBoss 6 I came to the conclusion that the response code must be set after you call getWriter to disable the Jboss custom error page response. I guess the implementation provides different writers depending on the status of the response.
使用 JBoss 6 我得出的结论是,必须在调用 getWriter 以禁用 Jboss 自定义错误页面响应后设置响应代码。我猜该实现根据响应的状态提供了不同的编写器。
response.getWriter().print(message);
response.setStatus(500);
回答by Jarekczek
Seems like all the APIs designed for setting the reason phrase in HTTP are getting obsolete because of this:
似乎所有用于在 HTTP 中设置原因短语的 API 都已过时,因为:
RFC 7230, Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing, June 2014. Section 3.1.2:
RFC 7230,超文本传输协议 (HTTP/1.1):消息语法和路由,2014 年 6 月。第 3.1.2 节:
The reason-phrase element exists for the sole purpose of providing a textual description associated with the numeric status code, mostly out of deference to earlier Internet application protocols that were more frequently used with interactive text clients. A client SHOULD ignore the reason-phrase content.
原因短语元素的唯一目的是提供与数字状态代码相关的文本描述,主要是出于对更频繁用于交互式文本客户端的早期 Internet 应用程序协议的尊重。 客户端应该忽略原因短语内容。
Tomcat removed support for org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER
property in version 8.5.0.
Tomcatorg.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER
在8.5.0 版本中删除了对属性的支持。