java.lang.IllegalStateException異常產生的緣由及解決辦法

java.lang.IllegalStateException異常產生的緣由及解決辦法  

錯誤類型大體爲如下幾種:
java.lang.IllegalStateException
Cannot   forward   a   response   that   is   already   committed 
IllegalStateException:response already commited 
IllegalStateException:getOutputStream() has already been called for this request
…………
錯誤緣由:
  
該異常表示,當前對客戶端的響應已經結束,不能在響應已經結束(或說消亡)後再向客戶端(其實是緩衝區)輸出任何內容。 java

具體分析: web

首先解釋下flush(),咱們知道在使用讀寫流的時候數據先被讀入內存這個緩衝區中, 而後再寫入文件,可是當數據讀完時不表明數據已經寫入文件完畢,由於可能還有一部分仍未寫入文件而留在內存中,這時調用flush()方法就會把緩衝區的數據強行清空輸出,所以flush()的做用就是保證緩存清空輸出。response是服務端對客戶端請求的一個響應,其中封裝了響應頭、狀態碼、內容等,服務端在把response提交到客戶端以前,會向緩衝區內寫入響應頭和狀態碼,而後將全部內容flush。這就標誌着該次響應已經committed(提交)。對於當前頁面中已經committed(提交)response,就不能再使用這個response向緩衝區寫任何東西(注:同一個頁面中的response.XXX()是同一個response的不一樣方法,只要其中一個已經致使了committed,那麼其它相似方式的調用都會致使 IllegalStateException異常)。

【注意】可以致使響應已經committed的操做包括:forward, redirect, flushBuffer
JDK API
緩存

①    flushBuffer
 public void flushBuffer()throws IOException
Forces any content in the buffer to be written to the client. A call to this method automatically commits the response, meaning the status code and headers will be written. tomcat

②       sendRedirect
 public void sendRedirect(String location)throws IOException
Sends a temporary redirect response to the client using the specified redirect location URL. This method can accept relative URLs; the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI. If the location is relative with a leading '/' the container interprets it as relative to the servlet container root.
If the response has already been committed, this method throws an IllegalStateException. After using this method, the response should be considered to be committed and should not be written to. 服務器

③    forward
public void forward(ServletRequest request,ServletResponse response) throws ServletException,IOException Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response.
For a RequestDispatcher obtained via getRequestDispatcher(), the ServletRequest object has its path elements and parameters adjusted to match the path of the target resource.
forward should be called before the response has been committed to the client (before response body output has been flushed). If the response already has been committed, this method throws an IllegalStateException. Uncommitted output in the response buffer is automatically cleared before the forward.
The request and response parameters must be either the same objects as were passed to the calling servlet's service method or be subclasses of the ServletRequestWrapper or ServletResponseWrapper classes that wrap them.
   注:注:在一次響應commit以前,全部的內容輸出都將寫入servlet引擎的緩衝區(tomcatweblogic的內容空間), 而在commit以後,上一次response向緩衝區寫入的內容,將清空。因爲servlet在沒有設置單線程的狀況下(使用Single-Threaded Modelservlet實現SingleThreadModel接口,jsp使用<%@ page isThreadSafe="false" %>),是多線程的,因此上面所說的緩衝區,都將是該response所屬的線程私有的內存空間。有了這個概念,將能夠分析碰到的關於servlet多線程的不少問題。若是不能確認response是否已經committed. 能夠調用response.isCommitted()來判斷。致使這個錯誤最廣泛的緣由是,jsp有編譯錯誤。
常看法決辦法: 多線程

①    response.sendRedirect()方法後加return語句便可,以下: app

 response.sendRedirect("login.jsp"); jsp

 return; ide

②    查提交的url是否有誤。 this

③若是你的頁面中用了清緩存代碼response.flushbuffer();又用到了response.sendRedirect(url);

你能夠把response.flushbuffer();去掉,或者用JSwindow.location.href="url";來作轉向。

④若是你用了OutputStream,而web容器生成的servlet代碼中有out.write(」」),這個和JSP中調用的
response.getOutputStream()
衝突。out.write()這個是字符流,而response.getOutputStream()是字節流,你不能在同一個頁面中調用多個輸出流。不管先調用哪個,在調用第二個時都會拋出IllegalStateException,由於在jsp中,out變量是經過response.getWriter獲得的。在多個使用了 outputStream的<%%>語句之間不能有空格及多餘的字符。也就是頁面中除了使用了outputStream的<%%>以外不能有空格或其它任何字符,在以內的語句能夠有空格及回車。

JSP頁面作輸出的時候有兩種方式.一是經過JspWriter,另外一個是經過OutputStream,但兩者互相排斥.若是並存的話就會報告以上異常.在不得不使用OutputStream的時候.咱們必需要把JspWriter捨棄掉了。找到請求異常的頁面所對應的Servlet..把其中全部使用JspWriter的語句所有去掉.或者是到你的JSP文件裏把動態輸出的代碼註釋掉.這裏注意換行和空格製表符均爲JspWriter輸出.應該一塊兒去掉.保存文件從新啓動服務器你會發現上述異常 消失了。
因爲jsp container在處理完成請求後會調用releasePageContet方法釋放所用的PageContext object,而且同時調用getWriter方法,因爲getWriter方法與在jsp頁面中使用流相關的getOutputStream方法衝突,因此會形成這種異常,解決辦法是:只須要在jsp頁面的最後加上兩條語句:   

                 out.clear(); 
                 out=pageContext.pushBody();

便可(其中out,pageContext均爲jsp內置對象!)

相關文章
相關標籤/搜索