2010-10-07 81 views
8

同時設置錯誤信息和身體我想寫一個servlet將返回像這樣的HTTP響應:從servlet的

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

<longer custom message> 

的原因是,我希望有一個編程客戶端,以便能夠處理響應消息採取特定的迴應,但我也想用更長的解釋填寫響應主體,以便使用瀏覽器很容易。

現在,HttpServletResponse有一個sendError(int,String)方法,它允許我指定錯誤代碼和消息。 javadocs只是說這個消息會嵌入到某種html頁面中,但是沒有關於設置http響應消息的信息。調用這個方法後,你不能寫任何其他的東西給響應。在我的測試中(使用jetty),該消息既用於http響應,也用於html body,這對我來說很好,除了我想指定兩個不同的字符串並且我不認爲http響應的設置消息通過不同的實現來保證。

還有一個你可以用任何代碼調用的setStatus(int)方法,然後你可以編寫你自己的html主體。這很接近,除了你不能指定http響應消息。

最後,有一個setStatus(int,String)方法實際上完全符合我的要求,但由於某種不明確性而不推薦使用。我假設一些servlet容器正在將消息寫入響應主體並關閉響應。

除了使用已棄用的方法,我假設我在這裏搞砸了,但我很好奇,如果其他人知道任何技巧?

回答

5

您可以通過在web.xml中指定錯誤的特定頁面自定義錯誤頁:

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

在你可以使用請求JSP文件屬性顯示自定義消息和其他信息。

+0

謝謝,這是一個很好的觀點,可能會幫助大多數人解決這個問題:)我碰巧在沒有整個網絡應用程序設置的情況下使用嵌入式碼頭:這是一個完全獨立的servlet。我至少可以查看是否可以用代碼設置錯誤頁面,但我可能會確定編程調用者只是在主體中查看細節。 – 2010-10-07 21:13:27

+0

只是想提一下我碰到的一個警告。如果嘗試使用html頁面而不是jsp,服務器將不會發送正確的狀態碼,儘管會顯示錯誤頁面內容。 – Asa 2012-05-14 06:34:34

9

還有一個你可以用任何代碼調用的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>"); 
    } 
} 

的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> 

和輸出:

$ 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 
+0

是的,我所引用的問題的一部分表明我明白這個選項。它還指出,這不允許您設置http響應消息(您的示例中的「Internal Server Error」,由servlet容器自動提供)。 – 2010-10-08 21:02:07

+0

即使'response.setStatus(int,String)'已被棄用,您*應該*能夠使用它來設置狀態行消息 – 2010-10-09 15:09:31

0

如果你想在頭爲什麼自定義錯誤消息不加你自己的標題與response.addHeader(String, String)?將這與馬特b的答案結合起來可以完成這項工作。

1

對不起,有一個錯誤響應正文的最明顯的原因是在錯誤發生時,在瀏覽器中顯示可讀的內容。這就是爲什麼生成HTML是Servlet規範中sendError的默認行爲的原因。

在我的情況下,我想要一些不同的東西,因爲我正在創建Web服務,如果一切正常,這個具體的東西不會返回響應。

0

使用JBoss 6我得出結論,在調用getWriter禁用Jboss自定義錯誤頁面響應之後,必須設置響應代碼。我想這個實現根據響應的狀態提供了不同的編寫者。

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

好像設計用於設定在HTTP的原因短語的所有API因爲這個越來越過時:

RFC 7230,超文本傳輸​​協議(HTTP/1.1):消息句法和路由, 2014年6月Section 3.1.2

原因短語元素存在提供 與數字狀態代碼, MOS相關的文字描述的唯一目的不再考慮更早用於交互式文本客戶端的較早的互聯網應用協議 。 A 客戶端應該忽略原因短語內容

Tomcat刪除了org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER財產version 8.5.0的支持。

+0

謝謝。在這一點上,我不再記得爲什麼我想讓客戶能夠檢查原因詞組,但它似乎並不是一個好主意。 – 2017-09-04 00:09:06