java.lang.IllegalStateException: STREAM at org.eclipse.jetty.server.Response.getWriter(Response.java:707)
java.lang.IllegalStateException: WRITER at org.eclipse.jetty.server.Response.getOutputStream(Response.java:681)
今天在写一个框架的时候遇到一个问题,记录一下,报错如上,查看javax.servlet.ServletResponse接口中的定义如下:
/** * Returns a {@link ServletOutputStream} suitable for writing binary * data in the response. The servlet container does not encode the * binary data. * <p> Calling flush() on the ServletOutputStream commits the response. * Either this method or {@link #getWriter} may * be called to write the body, not both. * * @return a {@link ServletOutputStream} for writing binary data * * @exception IllegalStateException if the <code>getWriter</code> method * has been called on this response * * @exception IOException if an input or output exception occurred * * @see #getWriter * */ public ServletOutputStream getOutputStream() throws IOException;
/** * Returns a <code>PrintWriter</code> object that * can send character text to the client. * The <code>PrintWriter</code> uses the character * encoding returned by {@link #getCharacterEncoding}. * If the response's character encoding has not been * specified as described in <code>getCharacterEncoding</code> * (i.e., the method just returns the default value * <code>ISO-8859-1</code>), <code>getWriter</code> * updates it to <code>ISO-8859-1</code>. * <p>Calling flush() on the <code>PrintWriter</code> * commits the response. * <p>Either this method or {@link #getOutputStream} may be called * to write the body, not both. * * * @return a <code>PrintWriter</code> object that * can return character data to the client * * @exception UnsupportedEncodingException * if the character encoding returned * by <code>getCharacterEncoding</code> cannot be used * * @exception IllegalStateException * if the <code>getOutputStream</code> * method has already been called for this * response object * * @exception IOException * if an input or output exception occurred * * @see #getOutputStream * @see #setCharacterEncoding * */ public PrintWriter getWriter() throws IOException;
注意这两句:
Either this method or {@link #getWriter} may be called to write the body, not both.
Either this method or {@link #getOutputStream} may be called to write the body, not both.
再看jetty的源码,jetty.server.Response的源码:
public ServletOutputStream getOutputStream() throws IOException { if (_outputState!=NONE && _outputState!=STREAM) throw new IllegalStateException("WRITER"); ServletOutputStream out = _connection.getOutputStream(); _outputState=STREAM; return out; }
public PrintWriter getWriter() throws IOException { if (_outputState!=NONE && _outputState!=WRITER) throw new IllegalStateException("STREAM"); /* if there is no writer yet */ if (_writer==null) { /* get encoding from Content-Type header */ String encoding = _characterEncoding; if (encoding==null) { /* implementation of educated defaults */ if(_cachedMimeType != null) encoding = MimeTypes.getCharsetFromContentType(_cachedMimeType); if (encoding==null) encoding = StringUtil.__ISO_8859_1; setCharacterEncoding(encoding); } /* construct Writer using correct encoding */ _writer = _connection.getPrintWriter(encoding); } _outputState=WRITER; return _writer; }
从源码的第3-4行可以得以验证,也就是说对于同一个response实例你只能使用其中的一个方法,不能两者混用。