2010-05-17 21 views
4

我有一個簡單的(Servlet,JSP和JSTL)Web應用程序,其主要功能是顯示從後端服務器檢索的圖像。控制器servlet將用戶轉發給JSP,然後JSP使用另一個Servlet在相同的JSP上顯示結果圖像。再往下,在JSP具有類似於行:如何處理來自圖像生成Servlet的異常?

<a href="<c:out value='${imageURL}'/>"><img src="<c:out value='${imageURL}'/>" alt="image view" border="1"></a> 

其中調用了圖像生成的servlet使其產生圖像的GET請求。

我的問題是:如何處理由此圖像生成servlet引發的異常?

我已經定義了一個錯誤頁面(在web.xml中)來處理我的web應用程序中的ServletException,但這不適用於此圖像生成Servlet,並導致在我的Tomcat服務器日誌中顯示以下錯誤:

SEVERE: Exception Processing ErrorPage[exceptionType=javax.servlet.ServletException, location=/WEB-INF/ExceptionPage.jsp] 
java.lang.IllegalStateException: Cannot reset buffer after response has been committed 

在這種情況下我的追求是什麼?

我希望能夠處理從此圖像生成Servlet拋出的異常,並在主UI上顯示一些錯誤或將用戶轉發到另一個錯誤頁面。

回答

3

您不能將響應更改爲重定向到錯誤頁面,而發送響應。現在改變整個響應已經太晚了。你不能要求那些已經從客戶端發回的字節。這就是IllegalStateException代表的地方。這是一個不歸路。

你可以做的最好的事情就是記錄異常,或者重寫代碼,以便在業務邏輯還沒有完成的時候它不會寫任何位給響應(也不會設置響應頭)任務呢。一旦你確定業務邏輯沒有拋出任何異常,那麼就開始寫(並因此間接地提交)響應。如果業務邏輯在響應尚未觸及時拋出異常,那麼您可以安全地將其拋出,以便在錯誤頁面中結束。儘管在圖像servlet的情況下,您可能還想將一些標準的404.gif串流到響應中。這是因爲您不能在<img>元素中顯示另一個HTML(錯誤)頁面,並且也不能更改父JSP/HTML頁面的URL,因爲這涉及到不同的請求。

+0

感謝您的解釋 - 現在有道理!我希望能夠流傳一個罐頭404.gif圖像;問題在於我的圖像Servlet可能會返回GIF,PNG,TIFF或PDF - 因此,只有一種類型的異常會生成很多圖像 - 商業邏輯在生成圖像時可能會拋出三種異常中的任何一種。 我喜歡你的想法,不寫任何東西到響應,直到我100%確定業務邏輯沒有拋出異常。 – ssahmed555 2010-05-17 19:18:32

+0

只需根據圖像擴展名設置「Content-Type」標頭即可。你可以爲'404.gif'修復它,或者使用'getServletContext()。getMimeType(filename)'來做這件事。您可以從[本文](http://balusc.blogspot.com/2007/04/imageservlet.html)中獲得一些想法。 – BalusC 2010-05-17 19:19:30

0

首先,確定爲什麼拋出非法狀態異常。與其處理拋出的異常,你可能只想修復你的代碼,使其消失。

1

根據servlet API,沒有servlet應該在同一個響應對象上調用getWriter()和getOutputStream(),因爲它會導致IllegalStateException。通常這是這個例外的來源。如果你輸出二進制數據像圖像文件,你應該使用getOutputStream()。

+1

調用兩個'的getWriter()'和'的getOutputStream()'確實也產生'IllegalStateException',但與完全不同的信息,比如'getWriter已經被調用了這個響應'。這在這裏不是問題。 – BalusC 2010-05-17 19:04:15

+0

我的圖像生成Servlet只調用getOutputStream()。所以這不是我得到IllegalStateException的原因。 – ssahmed555 2010-05-17 19:07:46

1

看起來像你的問題是在你的ExceptionPage.jsp中,而不是你的servlet代碼。

java.lang.IllegalStateException:響應已 一直致力於你已經試圖發送一個響應

手段後 不能復位緩衝區。 也許你已經直接打開了一個輸出流並向它寫了一些數據。一旦你完成了它,你就不能嘗試在響應中設置標題等等(它們已經到了客戶端)。

你需要做一個更好的狀態管理。最好的辦法是將請求預處理與響應生成分開。一旦你寫回應,你只能做或死。爲此,請檢查您是否從響應輸出中捕獲IOExceptions,將它們封裝到ServletException並將它們重定向到錯誤頁面。你真的無法在當前請求的上下文中處理它們。

+0

正確的是 - 我已經設置了內容類型,並在發生異常時打開OutputStream。 你說得對:我需要重新制作圖像生成servlet。 – ssahmed555 2010-05-17 19:10:08

0

你應該捕捉異常,並且使用的RequestDispatcher到所需的頁面轉發請求:

public void doGet(HttpServletRequest request, 
       HttpServletResponse response) 
throws ServletException, IOException { 

// The following piece of code results in NumberFormatException which will 
// be detected by the container. The RequestDispatcher object will forward 
// the same request to the other resource, here the file: forwardedJSP.jsp 
try { 
    int test = Integer.parseInt("abc"); 
} catch (NumberFormatException nfe) { 
    RequestDispatcher rd = request.getRequestDispatcher("/forwardedJSP.jsp"); 
    rd.forward(request, response); 
}} 
+0

他已經在'web.xml'中定義了一個'error-page',它基本上和這個一樣,但是更好的做法。整個問題只是他無法顯示這個錯誤頁面。 – BalusC 2010-05-17 19:11:23

+0

感謝您澄清,您的答案現在很有意義。 – Snehal 2010-05-17 19:24:39

相關問題