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

1.問題描述:html

  在導出數據庫某時間段的數據,而後得到Excel,雖然頁面能夠順利導出,但後臺報錯以下:(雖然不影響導出效果,但看到後臺的異常,心裏仍是不舒服的)java

嚴重: Servlet.service() for servlet [jsp] in context with path [/exportExcel] threw exception [java.lang.IllegalStateException: getOutputStream() has already been called for this response] with root cause
java.lang.IllegalStateException: getOutputStream() has already been called for this response
    at org.apache.catalina.connector.Response.getWriter(Response.java:678)
    at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:213)
    at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
    at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
    at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:194)
    at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:126)
    at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
    at org.apache.jsp.export_jsp._jspService(export_jsp.java:566)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:439)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

  從字義上分析:getOutputStream()已經調用了這個響應,就是重複被調用引發的異常。web

2.問題分析:數據庫

  在tomcat下jsp出現該錯誤通常都是在使用了輸出流(如輸出圖片驗證碼,文件下載等)。apache

  產生這樣的異常緣由:是web容器生成的servlet代碼中有out.write(""),這個和JSP中調用的response.getOutputStream()產生衝突。即Servlet規範說明,不能既調用response.getOutputStream(),又調用response.getWriter(),不管先調用哪個,在調用第二個時候應會拋出IllegalStateException,由於在jsp中,out變量其實是經過response.getWriter獲得的,你的程序中既用了response.getOutputStream,又用了out變量,故出現以上錯誤。緩存

3.解決方案:tomcat

  在調用 response.getOutputStream()以前,清空緩存的內容,並返回一個新的BodyContext,更新PageContext的out屬性的內容。websocket

...
<body>
<% String startDate = request.getParameter("startDate"); String endDate = request.getParameter("endDate"); System.out.println("起始時間:"+startDate+" &&& 終止時間"+endDate); if(startDate== null || startDate.equals("")){ startDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); System.out.println("起始時間:"+startDate); } if(endDate== null || endDate.equals("")){ endDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); System.out.println(endDate); }else{ endDate = endDate+" 23:59:59"; System.out.println("終止時間:"+endDate); } String fileName = new Date().getTime()+".xls"; response.reset(); response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "inline;filename="+fileName); out.clear(); //清空緩存的內容 out=pageContext.pushBody(); //更新PageContext的out屬性的內容 writeExcel(response.getOutputStream(),startDate,endDate); %>
</body>
</html>
<%!    //至關於全局聲明,是jsp頁面中一些變量和方法的聲明時用到的;上面沒有感嘆號的只是普通的語句 jsp代碼塊
    public static void writeExcel(OutputStream os,String startDate,String endDate){
        try{
            WritableWorkbook wwb = Workbook.createWorkbook(os);
            WritableSheet sheet = wwb.createSheet("導出表單", 0);  //第一個sheet
            // 設置字體
            WritableFont redfont = new WritableFont(WritableFont.createFont("微軟雅黑"),10, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.RED);
            // **************往工做表中添加數據*****************
            WritableCellFormat red_key = new WritableCellFormat(redfont);
            WritableFont black_font = new WritableFont(WritableFont.createFont("微軟雅黑"),10, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE,Colour.BLACK);
            WritableCellFormat black_key = new WritableCellFormat(black_font);
            // **************往工做表中添加表頭*****************
...
...

4.擴展session

  上面代碼,根本沒有用到out,爲何能夠調用out.clear和pageContext ? 由於這都是JSP的內置對象,能夠隨時使用。app

  JSP九大內置對象(在JSP頁面上可直接使用,html頁面不能用):

  4.1 page:一個jsp就是一個servlet類,就是一個java類,java類的this對象,對應JSP的page對象;

  4.2 pageContext :當前頁對象

  4.3 application:上下文對象

  4.4 config :servlet生命週期 1.初始化

  4.5 request:請求。servlet生命週期 2.service方法:請求,響應

  4.6 response:響應

  4.7 session:請求對應session,有了request就能夠獲得session,session=request.getSession();

  4.8 out:response對應out對象--》這個就是這個異常根本所在;

  4.9 exception:異常對象(有代碼存在就會有異常存在)。

相關文章
相關標籤/搜索