天天看點

工作架構各種使用整理 -- 通路圖檔的時候通路成功但是會有錯誤日志處理及分析

最初實作的方式如下:

<service verb="get" noun="ProductCategoryContentFile">
        <in-parameters>
            <parameter name="productCategoryContentId" required="true"/>
        </in-parameters>
        <actions>
            <entity-find-one entity-name="mantle.product.category.ProductCategoryContent" value-field="productCategoryContent"/>
            <if condition="productCategoryContent?.contentLocation">
                <script>ec.web.sendResourceResponse(productCategoryContent.contentLocation, true)</script>
            </if>
        </actions>
    </service>      

執行結果中圖檔可以展示出來,如果使用tomcat伺服器的話是沒有問題的,但是如果是在jetty中的話檢視console的時候會出現如下的log

日志内容如下:

1 14:06:12.151  WARN 48402763-759      o.moqui.i.c.TransactionFacadeImpl Transaction rollback for [Error running transition in [http://localhost:8080/rest/s1/slp/products/categories/contents/100001/file]]. Here is the current location: 
  2 org.moqui.BaseException: Rollback location
  3     at org.moqui.impl.context.TransactionFacadeImpl.rollback(TransactionFacadeImpl.groovy:415) [moqui-framework-2.0.0.jar:2.0.0]
  4     at org.moqui.impl.context.TransactionFacadeImpl.rollback(TransactionFacadeImpl.groovy:398) [moqui-framework-2.0.0.jar:2.0.0]
  5     at org.moqui.impl.screen.ScreenRenderImpl.internalRender(ScreenRenderImpl.groovy:349) [moqui-framework-2.0.0.jar:2.0.0]
  6     at org.moqui.impl.screen.ScreenRenderImpl.render(ScreenRenderImpl.groovy:176) [moqui-framework-2.0.0.jar:2.0.0]
  7     at org.moqui.impl.webapp.MoquiServlet.doScreenRequest(MoquiServlet.groovy:79) [moqui-framework-2.0.0.jar:2.0.0]
  8     at org.moqui.impl.webapp.MoquiServlet.service(MoquiServlet.groovy:54) [moqui-framework-2.0.0.jar:2.0.0]
  9     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [moqui-2.0.0.war:3.1.0]
 10     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837) [moqui-2.0.0.war:9.3.10.v20160621]
 11     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689) [moqui-2.0.0.war:9.3.10.v20160621]
 12     at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.d(WebSocketUpgradeFilter.java:225) [moqui-2.0.0.war:9.3.10.v20160621]
 13     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676) [moqui-2.0.0.war:9.3.10.v20160621]
 14     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581) [moqui-2.0.0.war:9.3.10.v20160621]
 15     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [moqui-2.0.0.war:9.3.10.v20160621]
 16     at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [moqui-2.0.0.war:9.3.10.v20160621]
 17     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [moqui-2.0.0.war:9.3.10.v20160621]
 18     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [moqui-2.0.0.war:9.3.10.v20160621]
 19     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) [moqui-2.0.0.war:9.3.10.v20160621]
 20     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [moqui-2.0.0.war:9.3.10.v20160621]
 21     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [moqui-2.0.0.war:9.3.10.v20160621]
 22     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [moqui-2.0.0.war:9.3.10.v20160621]
 23     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [moqui-2.0.0.war:9.3.10.v20160621]
 24     at org.eclipse.jetty.server.Server.handle(Server.java:524) [moqui-2.0.0.war:9.3.10.v20160621]
 25     at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) [moqui-2.0.0.war:9.3.10.v20160621]
 26     at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) [moqui-2.0.0.war:9.3.10.v20160621]
 27     at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) [moqui-2.0.0.war:9.3.10.v20160621]
 28     at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) [moqui-2.0.0.war:9.3.10.v20160621]
 29     at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [moqui-2.0.0.war:9.3.10.v20160621]
 30     org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [moqui-2.0.0.war:9.3.10.v20160621]
 31     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [moqui-2.0.0.war:9.3.10.v20160621]
 32     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [moqui-2.0.0.war:9.3.10.v20160621]
 33     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [moqui-2.0.0.war:9.3.10.v20160621]
 34     at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [moqui-2.0.0.war:9.3.10.v20160621]
 35     at java.lang.Thread.run(Thread.java:745) [?:1.8.0_77]
 36 14:06:12.153 ERROR 48402763-759                   o.m.i.w.MoquiServlet Internal error processing request: STREAM
 37 java.lang.IllegalStateException: STREAM
 38     at org.eclipse.jetty.server.Response.getWriter(Response.java:891) ~[?:?]
 39     at org.moqui.impl.context.WebFacadeImpl.sendJsonError(WebFacadeImpl.groovy:647) ~[moqui-framework-2.0.0.jar:2.0.0]
 40     at org.moqui.impl.context.WebFacadeImpl.handleServiceRestCall(WebFacadeImpl.groovy:1184) ~[moqui-framework-2.0.0.jar:2.0.0]
 41     at org.moqui.context.WebFacade$handleServiceRestCall.call(Unknown Source) ~[?:?]
 42     at rest_xml_transition_s1_actions.run(rest_xml_transition_s1_actions:6) ~[script:?]
 43     at org.moqui.impl.actions.XmlAction.run(XmlAction.groovy:66) ~[moqui-framework-2.0.0.jar:2.0.0]
 44     at org.moqui.impl.screen.ScreenDefinition$TransitionItem.run(ScreenDefinition.groovy:701) ~[moqui-framework-2.0.0.jar:2.0.0]
 45     at org.moqui.impl.screen.ScreenRenderImpl.recursiveRunTransition(ScreenRenderImpl.groovy:239) ~[moqui-framework-2.0.0.jar:2.0.0]
 46     at org.moqui.impl.screen.ScreenRenderImpl.recursiveRunTransition(ScreenRenderImpl.groovy:233) ~[moqui-framework-2.0.0.jar:2.0.0]
 47     at org.moqui.impl.screen.ScreenRenderImpl.internalRender(ScreenRenderImpl.groovy:347) ~[moqui-framework-2.0.0.jar:2.0.0]
 48     at org.moqui.impl.screen.ScreenRenderImpl.render(ScreenRenderImvy:176) ~[moqui-framework-2.0.0.jar:2.0.0]
 49     at org.moqui.impl.webapp.MoquiServlet.doScreenRequest(MoquiServlet.groovy:79) [moqui-framework-2.0.0.jar:2.0.0]
 50     at org.moqui.impl.webapp.MoquiServlet.service(MoquiServlet.groovy:54) [moqui-framework-2.0.0.jar:2.0.0]
 51     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [moqui-2.0.0.war:3.1.0]
 52     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837) [moqui-2.0.0.war:9.3.10.v20160621]
 53     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689) [moqui-2.0.0.war:9.3.10.v20160621]
 54     at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225) [moqui-2.0.0.war:9.3.10.v20160621]
 55     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676) [moqui-2.0.0.war:9.3.10.v20160621]
 56     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581) [moqui-2.0.0.war:9.3.10.v20160621]
 57     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [moqui-2.0.0.war:9.3.10.v20160621]
 58     at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [moqui-2.0.0.war:9.3.10.v20160621]
 59     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [moqui-2.0.0.war:9.3.10.v20160621]
 60     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [moqui-2.0.0.war:9.3.10.v20160621]
 61     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) [moqui-2.0.0.war:9.3.10.v20160621]
 62     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [moqui-2.0.0.war:9.3.10.v20160621]
 63     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [moqui-2.0.0.war:9.3.10.v20160621]
 64     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [moqui-2.0.0.war:9.3.10.v20160621]
 65     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [moqui-2.0.0.war:9.3.10.v20160621]
 66     at org.ejetty.server.Server.handle(Server.java:524) [moqui-2.0.0.war:9.3.10.v20160621]
 67     at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) [moqui-2.0.0.war:9.3.10.v20160621]
 68     at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) [moqui-2.0.0.war:9.3.10.v20160621]
 69     at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) [moqui-2.0.0.war:9.3.10.v20160621]
 70     at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) [moqui-2.0.0.war:9.3.10.v20160621]
 71     at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [moqui-2.0.0.war:9.3.10.v20160621]
 72     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [moqui-2.0.0.war:9.3.10.v20160621]
 73     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [moqui-2.0.0.war:9.3.10.v20160621]
 74     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [moqui-2.0.0.war:9.3.10.v20160621]
 75     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [moqui-2.0.0.war:9.3.10.v20160621]
 76     at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [moqui-2.0.0.war:9.3.10.v20160621]
 77     at java.lang.Thread.run(Thread.java:745) [?:1.8.0_77]
 78 14:06:12.165  WARN 48402763-759      o.moqui.i.c.TransactionFacadeImpl Rollback only not set on current transaction, status is STATUS_NO_TRANSACTION
 79 14:06:12.165 ERROR 48402763-759                   o.m.i.w.MoquiServlet Error rendering internal-error error screen, sending code 500 with message: STREAM
 80 java.lang.RuntimeException: Error rendering screen [component://webroot/screen/webroot.xml]
 81     at org.moqui.impl.screen.ScreenRenderImpl.doActualRender(ScreenRenderImpl.groovy:737) ~[moqui-framework-2.0.0.jar:2.0.0]
 82     at org.moqui.impl.screen.ScreenRenderImpl.internalRender(ScreenRenderImpl.groovy:594) ~[moqui-framework-2.0.0.jar:2.0.0]
 83        .moqui.impl.screen.ScreenRenderImpl.render(ScreenRenderImpl.groovy:176) ~[moqui-framework-2.0.0.jar:2.0.0]
 84     at org.moqui.impl.webapp.MoquiServlet.sendErrorResponse(MoquiServlet.groovy:142) [moqui-framework-2.0.0.jar:2.0.0]
 85     at org.moqui.impl.webapp.MoquiServlet.doScreenRequest(MoquiServlet.groovy:103) [moqui-framework-2.0.0.jar:2.0.0]
 86     at org.moqui.impl.webapp.MoquiServlet.service(MoquiServlet.groovy:54) [moqui-framework-2.0.0.jar:2.0.0]
 87     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [moqui-2.0.0.war:3.1.0]
 88     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837) [moqui-2.0.0.war:9.3.10.v20160621]
 89     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689) [moqui-2.0.0.war:9.3.10.v20160621]
 90     at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225) [moqui-2.0.0.war:9.3.10.v20160621]
 91     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676) [moqui-2.0.0.war:9.3.10.v20160621]
 92     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581) [moqui-2.0.0.war:9.3.10.v20160621]
 93     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [moqui-2.0.0.war:9.3.10.v20160621]
 94     at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [moqui-2.0.0.war:9.3.10.v20160621]
 95     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [moqui-2.0.0.war:9.3.10.v20160621]
 96     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [moqui-2.0.0.war:9.3.10.v20160621]
 97     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) [moqui-2.0.0.war:9.3.10.v20160621]
 98     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [moqui-2.0.0.war:9.3.10.v20160621]
 99     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [moqui-2.0.0.war:9.3.10.v20160621]
100     at org.eclipse.jetty.server.handler.ScopedHandler.handle(Scoped.java:141) [moqui-2.0.0.war:9.3.10.v20160621]
101     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [moqui-2.0.0.war:9.3.10.v20160621]
102     at org.eclipse.jetty.server.Server.handle(Server.java:524) [moqui-2.0.0.war:9.3.10.v20160621]
103     at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) [moqui-2.0.0.war:9.3.10.v20160621]
104     at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) [moqui-2.0.0.war:9.3.10.v20160621]
105     at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) [moqui-2.0.0.war:9.3.10.v20160621]
106     at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) [moqui-2.0.0.war:9.3.10.v20160621]
107     at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [moqui-2.0.0.war:9.3.10.v20160621]
108     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [moqui-2.0.0.war:9.3.10.v20160621]
109     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [moqui-2.0.0.war:9.3.10.v20160621]
110     at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [moqui-2.0.0.war:9.3.10.v20160621]
111     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [moqui-2.0.0.war:9.3.10.v20160621]
112     at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [moqui-2.0.0.war:9.3.10.v20160621]
113     at java.lang.Thread.run(Thread.java:745) [?:1.8.0_77]
114 Caused by: java.lang.IllegalStateException: STREAM
115     at org.eclipse.jetty.server.Response.getWriter(Response.java:891) ~[?:?]
116     at org.moqui.impl.screen.ScreenRenderImpl.getWriter(ScreenRenderImpl.groovy:107) ~[moqui-framework-2.0.0.jar:2.0.0]
117     at org.moqui.impl.screen.ScreenWidgets.render(ScreenWidgets.groovy:43) ~[moqui-framework-2.0.0.jar:2.0.0]
118     at org.moqui.impl.screen.ScreenSection.renderSingle(ScreenSection.groovy:140) ~[moqui-framework-2.0.0.jar:2.0.0]
119     at org.moquicreen.ScreenSection.render(ScreenSection.groovy:113) ~[moqui-framework-2.0.0.jar:2.0.0]
120     at org.moqui.impl.screen.ScreenDefinition.render(ScreenDefinition.groovy:459) ~[moqui-framework-2.0.0.jar:2.0.0]
121     at org.moqui.impl.screen.ScreenRenderImpl.doActualRender(ScreenRenderImpl.groovy:719) ~[moqui-framework-2.0.0.jar:2.0.0]
122     ... 32 more      

關于這個問題主要是和jetty處理getWriter和getOutputStream的方式有關:

在jetty中的處理方式如下:

1 這兩個方法在jetty容易中是這麼處理:
  2 org.eclipse.jetty.server.Response繼承自j2ee裡面的HttpServletResponse.java類
  3 org.eclipse.jetty.server.Response.java類裡面
  4 
  5     public ServletOutputStream getOutputStream() throws IOException
  6     {
  7         if (_outputState!=NONE && _outputState!=STREAM)    如果狀态為WRITER狀态,則抛出異常
  8             throw new IllegalStateException("WRITER");
  9 
 10         _outputState=STREAM;         把response狀态改為STREAM流狀态
 11         return _connection.getOutputStream();
 12     }
 13 
 14   public PrintWriter getWriter() throws IOException
 15     {
 16         if (_outputState!=NONE && _outputState!=WRITER)  如果狀态為STREAM,則抛出異常
 17             throw new IllegalStateException("STREAM");
 18 
 19         /* if there is no writer yet */
 20         if (_writer==null)
 21         {
 22             /* get encoding from Content-Type header */
 23             String encoding = _characterEncoding;
 24 
 25             if (encoding==null)
 26             {
 27                 /* implementation of educated defaults */
 28                 if(_mimeType!=null)
 29                     encoding = null; // TODO getHttpContext().getEncodingByMimeType(_mimeType);
 30 
 31                 if (encoding==null)
 32                     encoding = StringUtil.__ISO_8859_1;
 33 
 34                 setCharacterEncoding(encoding);
 35             }
 36 
 37             /* construct Writer using correct encoding */
 38             _writer = _connection.getPrintWriter(encoding);
 39         }
 40         _outputState=WRITER;             把response狀态改為WRITER狀态,
 41         return _writer;
 42     }
 43 
 44 也就是說在j2ee,web應用裡面不能同時打開PrintWriter和OutputStream,否則就是抛出上面那個異常。
 45 
 46 jetty的response裡面有三種狀态:
 47     public static final int
 48         NONE=0,  未調用getPrintWriter和getOutputStream之前的預設狀态
 49         STREAM=1,  二進制流狀态  調用getOutputStream之後的狀态
 50         WRITER=2;   字元流狀态
 51   
 52 
 53 解決方法:
 54    1.在應用中隻使用一個,要麼都用getPrintWriter,要麼都用getOutputStream。
 55    2.在webx 中的com.alibaba.citrus.service.requestcontext.buffered.impl.BufferedResponseImpl.java類中有下面這麼解決方案:
 56   
 57     /**
 58      * 取得輸出流。
 59      * 
 60      * @return response的輸出流
 61      * @throws IOException 輸入輸出失敗
 62      */
 63     @Override
 64     public ServletOutputStream getOutputStream() throws IOException {
 65         if (stream != null) {
 66             return stream;
 67         }
 68 
 69         if (writer != null) {
 70             // 如果getWriter方法已經被調用,則将writer轉換成OutputStream
 71             // 這樣做會增加少量額外的記憶體開銷,但标準的servlet engine不會遇到這種情形,
 72             // 隻有少數servlet engine需要這種做法(resin)。
 73             if (writerAdapter != null) {
 74                 return writerAdapter;
 75             } else {
 76                 log.debug("Attampt to getOutputStream after calling getWriter.  This may cause unnecessary system cost.");
 77                 writerAdapter = new WriterOutputStream(writer, getCharacterEncoding());
 78                 return writerAdapter;
 79             }
 80         }
 81 
 82         if (buffering) {
 83             // 注意,servletStream一旦建立,就不改變,
 84             // 如果需要改變,隻需要改變其下面的bytes流即可。
 85             if (bytesStack == null) {
 86                 bytesStack = new Stack<ByteArrayOutputStream>();
 87             }
 88 
 89             ByteArrayOutputStream bytes = new ByteArrayOutputStream();
 90 
 91             bytesStack.push(bytes);
 92             stream = new BufferedServletOutputStream(bytes);
 93 
 94             log.debug("Created new byte buffer");
 95         } else {
 96             stream = super.getOutputStream();
 97         }
 98 
 99         return stream;
100     }
101 
102     /**
103      * 取得輸出字元流。
104      * 
105      * @return response的輸出字元流
106      * @throws IOException 輸入輸出失敗
107      */
108     @Override
109     public PrintWriter getWriter() throws IOException {
110         if (writer != null) {
111             return writer;
112         }
113 
114         if (stream != null) {
115             // 如果getOutputStream方法已經被調用,則将stream轉換成PrintWriter。
116             // 這樣做會增加少量額外的記憶體開銷,但标準的servlet engine不會遇到這種情形,
117             // 隻有少數servlet engine需要這種做法(resin)。
118             if (streamAdapter != null) {
119                 return streamAdapter;
120             } else {
121                 log.debug("Attampt to getWriter after calling getOutputStream.  This may cause unnecessary system cost.");
122                 streamAdapter = new PrintWriter(new OutputStreamWriter(stream, getCharacterEncoding()), true);
123                 return streamAdapter;
124             }
125         }
126 
127         if (buffering) {
128             // 注意,servletWriter一旦建立,就不改變,
129             // 如果需要改變,隻需要改變其下面的chars流即可。
130             if (charsStack == null) {
131                 charsStack = new Stack<StringWriter>();
132             }
133 
134             StringWriter chars = new StringWriter();
135 
136             charsStack.push(chars);
137             writer = new BufferedServletWriter(chars);
138 
139             log.debug("Created new character buffer");
140         } else {
141             writer = super.getWriter();
142         }
143 
144         return writer;
145     }
146 
147 
148   是以在我們自己的應用中就不要再調用完j2ee的原生response的getPrintWriter之後再調用原生的getOutputStream(),或者調用原生的response的getOutputStream之後再調用getPrintWriter。      

 下面就IllegalStateException宜昌做分析:

web容器生成的servlet代碼中有out.write(""),這和response.getOutputStream()産生沖突。

servlet規範中有說明,不能既使用response.getOutputStream()又調用response.getWriter(),無論先調用哪一個,在調用第二個的時候就抛出IllegalStateException

基于此,我們可以通過增加out.clear()和outpageContext.pushBody來解決,在寫入圖檔的使用需要加入flush()