Response.getWriter() 和Response.getOutputStream衝突

From:http://yulimeander.blog.sohu.com/119195170.html
 
ava.lang.IllegalStateException異常:簡單分析和簡單解決方案
2008-07-19 18:07
今天寫java驗證碼程序,完成後使用一切正常,可是總拋出java.lang.IllegalStateException異常,雖然並不影響正常使用,但看了總讓人以爲很不舒服,檢查代碼並無錯,最後上網查了很多資料,終於發現緣由之所在。
咱們在作文件上傳或者下載,或者過濾等操做時,可能要用到頁面的輸出流.
例如在JSP使用:
response.reset();
response.setContentType(」application/vnd.ms-excel」);
OutputStream os = response.getOutputStream();  
拋出異常:
ERROR [Engine] StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
從網上找了下資料,綜合一下緣由分析:
這是web容器生成的servlet代碼中有out.write(」」),這個和JSP中調用的response.getOutputStream()產生衝突.
即Servlet規範說明,不能既調用 response.getOutputStream(),又調用response.getWriter(),不管先調用哪個,在調用第二個時候應會拋出 IllegalStateException,由於在jsp中,out變量是經過response.getWriter獲得的,在程序中既用了response.getOutputStream,又用了out變量,故出現以上錯誤。
解決方案:
1.在程序中添加:
out.clear();
out = pageContext.pushBody();
就能夠了;
2,不要在%][%之間寫內容包括空格和換行符
3,在頁面寫入圖片的時候,須要flush()
OutputStream output=response.getOutputStream();
output.flush();
4,在頁面肯定寫入<meta http-equiv=」Content-Type」 content=」text/html; charset=gb2312」>
孫衛琴說多是tomcat的bug,我給她回了封信:
:我看了看這裏,http://www.javathinker.org/main.jsp?bc=showessay.jsp+filename=tomcat/tomcat_question_chapter13.htm這裏是你回覆別人的一個帖子,裏面的觀點基本上和我理解的同樣,可是你最後寫到多是tomcat的bug,我想解釋一下:在jsp中,out是內嵌對象,即已經設置了PrintWriter out=response.getWriter();這樣在再次getOutputStream()獲得輸出流時(好比轉發過濾、下載文件時)就出錯了(寫排斥鎖),我不止一次看到有人的文件下載頁面在後臺不斷打印這個異常。而在servlet中沒有默認out內置對象,因此沒有出錯.你能夠在servlet中添加out對象試試,應該會報異常的.因此正確的處理方式就應該是:在servlet中作控制層,在業務處理之前不要得到out對象,當業務操做失敗或出現異常時再生成out對象回顯操做結果。

***********************************************************
response.getOutputStream() 和 requonse.getWriter() 區別

(1)使用tomcat5容器調用response.getOutputStream()方法便可實現,但調用requonse.getWriter()方法時,輸出二進制數據時(圖片等內容沒法顯示)則出現「getWriter() has already been called for this response」異常。
(2)使用tomcat6容器調用response.getOutputStream()方法時有中文字符會發生「java.io.CharConversionException:Not an ISO 8859-1 character:」異常,調用requonse.getWriter()方法時可實現文本字符串數據輸出,調用response.getOutputStream()方法可現實字節流數據的輸出。
    就上述出現的問題進行分析研究,閱讀了tomcat6的源代碼發現,在調用response.getOutputStream()方法時會判斷是否已調用了requonse.getWriter()方法;相反在調用requonse.getWriter()方法時會判斷是否已調用了response.getOutputStream()方法。
    在tomcat5時並無出現這個問題,使用response.getOutputStream()方法可現實兩種數據輸出,只是在使用requonse.getWriter()時發生異常,而在tomcat6下則必須針對不一樣的數據類型選擇相應輸出流,這時爲何呢?仔細閱讀tomcat6源代碼沒有發現問題的根源,給出的參考時:在一次客戶端請求的響應動做中,只能調用一種響應輸出方法,要麼是getWriter()要麼是getOutputStream(),且若是使用getOutputStream()方法輸出字符串格式的數據時,中文沒法正常經過將發生「java.io.CharConversionException:Not an ISO 8859-1 character:」異常,在tomcat5下沒有對getOutputStream()方法進行嚴格控制,中文字符串可正常經過。可見tomcat6的安全機制比tomcat5要嚴格,對於字符串格式的數據要求使用getWriter()方法輸出響應,若是使用了getOutputStream()方法輸出響應,則對輸出的字符串數據進驗證,要求高字節必須爲0,顯然中文是沒法經過的。html

相關文章
相關標籤/搜索