关于jetty和webx对于HttpServletResponse getWriter和getOutputStream的处理
2012-05-31 13:51
567 查看
这个异常经过在jetty的一个简单程序的测试验证,确定问题及分析如下:
这个程序在使用response输出结果时,先调用response的getWriter获得PrintWrite对象后输出内容,然后再调用getOutputStream方法获得outputStream对象后输出二进制内容,然后就跑出上面那个异常了。 这两个方法在jetty容易中是这么处理: org.eclipse.jetty.server.Response继承自j2ee里面的HttpServletResponse.java类 org.eclipse.jetty.server.Response.java类里面 public ServletOutputStream getOutputStream() throws IOException { if (_outputState!=NONE && _outputState!=STREAM) 如果状态为WRITER状态,则抛出异常 throw new IllegalStateException("WRITER"); _outputState=STREAM; 把response状态改为STREAM流状态 return _connection.getOutputStream(); } public PrintWriter getWriter() throws IOException { if (_outputState!=NONE && _outputState!=WRITER) 如果状态为STREAM,则抛出异常 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(_mimeType!=null) encoding = null; // TODO getHttpContext().getEncodingByMimeType(_mimeType); if (encoding==null) encoding = StringUtil.__ISO_8859_1; setCharacterEncoding(encoding); } /* construct Writer using correct encoding */ _writer = _connection.getPrintWriter(encoding); } _outputState=WRITER; 把response状态改为WRITER状态, return _writer; } 也就是说在j2ee,web应用里面不能同时打开PrintWriter和OutputStream,否则就是抛出上面那个异常。 jetty的response里面有三种状态: public static final int NONE=0, 未调用getPrintWriter和getOutputStream之前的默认状态 STREAM=1, 二进制流状态 调用getOutputStream之后的状态 WRITER=2; 字符流状态 解决方法: 1.在应用中只使用一个,要么都用getPrintWriter,要么都用getOutputStream。 2.在webx 中的com.alibaba.citrus.service.requestcontext.buffered.impl.BufferedResponseImpl.java类中有下面这么解决方案: /** * 取得输出流。 * * @return response的输出流 * @throws IOException 输入输出失败 */ @Override public ServletOutputStream getOutputStream() throws IOException { if (stream != null) { return stream; } if (writer != null) { // 如果getWriter方法已经被调用,则将writer转换成OutputStream // 这样做会增加少量额外的内存开销,但标准的servlet engine不会遇到这种情形, // 只有少数servlet engine需要这种做法(resin)。 if (writerAdapter != null) { return writerAdapter; } else { log.debug("Attampt to getOutputStream after calling getWriter. This may cause unnecessary system cost."); writerAdapter = new WriterOutputStream(writer, getCharacterEncoding()); return writerAdapter; } } if (buffering) { // 注意,servletStream一旦创建,就不改变, // 如果需要改变,只需要改变其下面的bytes流即可。 if (bytesStack == null) { bytesStack = new Stack<ByteArrayOutputStream>(); } ByteArrayOutputStream bytes = new ByteArrayOutputStream(); bytesStack.push(bytes); stream = new BufferedServletOutputStream(bytes); log.debug("Created new byte buffer"); } else { stream = super.getOutputStream(); } return stream; } /** * 取得输出字符流。 * * @return response的输出字符流 * @throws IOException 输入输出失败 */ @Override public PrintWriter getWriter() throws IOException { if (writer != null) { return writer; } if (stream != null) { // 如果getOutputStream方法已经被调用,则将stream转换成PrintWriter。 // 这样做会增加少量额外的内存开销,但标准的servlet engine不会遇到这种情形, // 只有少数servlet engine需要这种做法(resin)。 if (streamAdapter != null) { return streamAdapter; } else { log.debug("Attampt to getWriter after calling getOutputStream. This may cause unnecessary system cost."); streamAdapter = new PrintWriter(new OutputStreamWriter(stream, getCharacterEncoding()), true); return streamAdapter; } } if (buffering) { // 注意,servletWriter一旦创建,就不改变, // 如果需要改变,只需要改变其下面的chars流即可。 if (charsStack == null) { charsStack = new Stack<StringWriter>(); } StringWriter chars = new StringWriter(); charsStack.push(chars); writer = new BufferedServletWriter(chars); log.debug("Created new character buffer"); } else { writer = super.getWriter(); } return writer; } 所以在我们自己的应用中就不要再调用完j2ee的原生response的getPrintWriter之后再调用原生的getOutputStream(),或者调用原生的response的getOutputStream之后再调用getPrintWriter。
相关文章推荐
- 关于jetty和webx对于HttpServletResponse getWriter和getOutputStream的处理
- 关于jetty和webx对于HttpServletResponse getWriter和getOutputStream的处理
- (5A)HttpServletResponse:getWriter和getOutputStream()、sendRedirect()、session(简单理解)、文件下载、页面缓存
- web服务器(jetty)处理请求出现NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I
- 验证调用HttpServletResponse.getWriter().close()方法是否真的会关闭http连接
- Response对象、HttpServletResponse简介、处理字节编码问题、实现动态文件下载
- Servlet的PrintWriter out = response.getWriter()使用
- HTTP协议处理框架 - 最简单的GET请求拼装和Response解析
- blade中设计中对于HttpResponse的封装处理
- 关于http客户端常见错误"警告:Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is rec"
- 关于浏览器对于html的input标签中name的命名特殊字符处理(GET)与script+js跨域实现
- Struts2之HttpServletRequest、HttpServletResponse,HttpSession,Parameters处理
- javax.servlet.http.HttpServletResponse.getStatus()I
- 关于Filter中ServletRequest和ServletResponse强转HttpServletRequest和HttpServletResponse安全问题(向下转型一定不安全吗?)
- Filter处理HttpServletRequest & HttpServletResponse 笔记
- 关于http客户端常见错误"警告:Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
- HttpServletRequest和HttpServletResponse实现登录(附乱码处理代码)(2017.9.28第一次修改版)
- ServletRequest的getRequestDispatcher().forward()和HttpResponseServlet.sendRedirect()
- 关于Servlet报错:405 HTTP method GET is not supported by this URL问题解决方法
- Web开发中关于servlet产生HTTP Status 404 - /webMVC/servlet/MyReturnMessage.jsp的处理