解決getWriter() has already been called for this response異常(轉)


近期,查看公司應用日志系統error錯誤信息時,發現了大量的nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response異常。這個錯誤以前見到過,也解決過。於是想着趁有點空閑,總結下該錯誤。如有不對,望各位多包容,歡迎交流。

一、應用日志文件中的錯誤信息

ERROR 977 --- [io-8686-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause

java.lang.IllegalStateException: getWriter() has already been called for this response

    at org.apache.catalina.connector.Response.getOutputStream(Response.java:575) ~[tomcat-embed-core-8.5.5.jar:8.5.5]

原因分析
IllegalStateException: getWriter() has already been called for this response

        從字面意思不難得出錯誤原因:HttpServletResponse中的PrintWriter已經被手動調用過了。所以當servlet執行到方法結果處理邏輯時,需要將返回值輸出到writer中去,這時發現PrintWriter已經被調用過。於是servlet認為這是使用混亂的邏輯錯誤,於是拋出錯誤。

        根本原因:在Controller接口方法中,既手動調用PrintWriter向客戶端輸出內容,又設置了方法返回值。導致servlet需要兩次將結果通過PrintWriter輸出到客戶端,結果報錯。

/**1.反例:驗證接口既手動調用PrintWriter輸出流flush,又return 返回值.

 * 驗證結果:客戶端ajax請求正常返回,但同時,服務端出現異常,org.springframework.web.util.NestedServletException: Request processing failed;

 * nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response

 * 結論:方法內已經執行過response輸出流write動作.

 * servlet再次通過response輸出流將返回值向客戶端發送時,發現輸出流已經被調用過,也就是getWriter()過。於是認為這是使用邏輯混亂,果斷報錯。

 * */

@RequestMapping(value="/checkGetWriterError", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public ServiceResponse<String> checkGetWriterError(HttpServletResponse response) throws Exception {

    log.info("驗證接口既手動調用輸出流flush,又return 返回值.造成異常!");

    PrintWriter printWriter = response.getWriter();

    printWriter.write(ServiceResponse.ok("來自printWriter的返回值").toString());

    printWriter.flush();//沒有該句也是報一樣錯.

    return ServiceResponse.ok("成功了,恭喜你.");

}

結果:程序正常返回結果,控制台出現異常。

(返回結果中編碼問題,不在本文討論范圍,請忽略)

 

 源碼佐證

 

 

二、擴展驗證附驗證結果

  • 驗證PrintWriter輸出流flush,無返回值

/**2.正例:驗證接口僅手動調用PrintWriter輸出流flush,無返回值.*/

@RequestMapping(value="/checkGetWriterError2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public void checkGetWriterError2(HttpServletResponse response) throws Exception {

    log.info("驗證接口手動調用PrintWriter輸出流, 無return 返回值. 接口正常執行無異常!");

    PrintWriter printWriter = response.getWriter();

    printWriter.write(ServiceResponse.ok("來自printWriter的返回值").toString());

    printWriter.flush();

}

結果:程序正常返回結果,控制台無異常。

(返回結果中編碼問題,不在本文討論范圍,請忽略)

 

 

調用ServletOutputStream輸出流flush,  無返回值

/**3.正例:驗證接口既手動調用ServletOutputStream輸出流flush,  無返回值.*/

@RequestMapping(value="/checkGetWriterError3", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public void checkGetWriterError3(HttpServletResponse response) throws Exception {

log.info("驗證接口手動調用ServletOutputStream輸出流, 無return 返回值. 接口正常執行無異常!");

    ServletOutputStream output = response.getOutputStream();

    output.write(ServiceResponse.ok("來自ServletOutputStream的返回值").toString().getBytes());

    output.flush();

}

結果:程序正常返回結果,控制台無異常。

 

 

調用ServletOutputStream輸出流flush,return 返回值

/**4.反例:驗證接口既手動調用ServletOutputStream輸出流flush,又return 返回值.*/

@RequestMapping(value="/checkGetWriterError4", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public ServiceResponse<String> checkGetWriterError4(HttpServletResponse response) throws Exception {

log.info("驗證接口手動調用ServletOutputStream輸出流, 又執行return 返回值. 接口返回異常!");

    ServletOutputStream output = response.getOutputStream();

    output.write(ServiceResponse.ok("來自ServletOutputStream的返回值").toString().getBytes());

    output.flush();

    return ServiceResponse.ok("來自return的返回值.");

}

結果:程序返回結果不正常,控制台無異常。

不僅ServletOutputStream輸出流中的內容被發送到客戶端,而且方法返回結果也輸出到客戶端。

————————————————
版權聲明:本文為CSDN博主「常樂_smile」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/li396864285/article/details/78122296


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM