大家猜一下结果,再去测试,很奇怪的事情。也许有些内幕没有搞清楚
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line屏幕输出啥?
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line屏幕输出啥?
解决方案 »
- 帮忙看个错误,什么意思
- 怎么有两个InputStream呢。怪了,不知道大家有没有碰到过
- 求JAVA小程序. 输入a*b , 输出结果,用clipse
- java中使用Runtime.getRuntime().exec调用mysqldump的问题
- 搞晕了,关于值相等和对象相等,欢迎探讨
- serverSocket.accept()的问题
- 关于编码转换的问题,我觉得java大斑竹(尤其是笑着悲伤)应该做一个faq,大家进来支持一下。
- 工作之余写的一个java版的小程序,可以聊聊天,发发帖子,请大家给些意见。
- !!!!!?????请问如何调用在类路径下,但不在任何包里的类?谢谢----急!百分相赠!!!
- 我刚刚开始学习java,有人能帮帮我吗?
- 做一个记事文体!
- Panel 对象的paintComponent 和 paint 有什么区别
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.flush();
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line我这么写就变成12121212了....狂汗...后台都会报出Stream closed的异常...
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.flush();
out.println("34343434");
out.clearBuffer();
out.println("56565656");
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line
这个输出又是12121212 56565656
出错之前out里面只要有东西就会被显示出来....
无论是outputStream还是writer....
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.flush();
os.close();
os = null;
out.clear();
out = pageContext.pushBody();
%>
a test line根据网上的说法,加上了out.clear();
out = pageContext.pushBody();就不报错,只是out不能输出了...
out.close();
OutputStream os = response.getOutputStream();明明已经关闭了,怎么还能输出呢?难道??? 搞不懂哦!!
而属性outputStream的属性ob和属性writer之下的属性ob,lock,out,都是OutputStream类型(当时id也都等于1586)而且outputStream和writer 的属性ob.bb(ByteChunk)的id也都一样(id=1582),并且ob.bb.bufer里面都存放了14字节的数据:116 104 105 115 32 105 115 32 116 101 115 116,正好是字符串"this is a test"的Unicode码...------------------------------------------------------------------------
所以我猜测,出现这种情况似乎因为response里的所有输出共用了一个outputBuffer.....
而response.getOutputStream是一个OutputStream对象
两个都是不同的东西,根本不会受到任何影响的。就算不采用response.getOutputStream而采用response.getWriter()
得到的Writer对象,与out中的Writer也是对象不一样的,可以通过
Writer os = response.getWriter();
System.out.println(out == os);
得知。实际上out对象是在Servlet容器初始化的时候就产生了,将其关掉以后后面
所有的页面都不会输出了。而response中的Writer只是在请求/响应阶段产
生的,每一个请求/响应都会产生一次对象的。
更正一下:out对象也是在请求/响应阶段产生的。但是out对象属于JspWriter,是从pageContext.getOut(),而getOut通过传入一个
response.getWriter对象而构建出来的。下面的是org.apache.jasper.runtime.JspWriterImpl中initOut的源代码:private void initOut() throws IOException {
if(out == null)
out = response.getWriter();
}从上面的代中可以看出,out其实就是一个response.getWriter,只不过对其进行了再次的封装。显式的调用out.close()时,做了以下的事情:public void close() throws IOException {
if(response == null || closed)
return;
flush();
if(out != null)
out.close();
out = null; // 在关闭的同时设为null了。
closed = true;
}在out.close()关闭后,实际上也把response中的out对象设为null。再看一下response中getWriter的源代码,org.apache.catalina.connector.Responsepublic PrintWriter getWriter() throws IOException {
if(usingOutputStream)
throw new IllegalStateException(sm.getString("coyoteResponse.getWriter.ise"));
setCharacterEncoding(getCharacterEncoding());
usingWriter = true;
outputBuffer.checkConverter();
if(writer == null)
writer = new CoyoteWriter(outputBuffer);
return writer;
}在response获得writer对象时,先判断过了其writer是否为null,若为null时,则重新生成一个。这也就是说在页面上 out.close()后,再使用response.getWriter()不会出错的原因。而楼主所用的response.getOutputStream与out就是两个不同的东西这是互不影响的。如果将页面代码改为:<%
Writer os = response.getWriter();
os.write(0x4e01);
os.close();
out.println("12121212");
%>可以输出一个“丁”字,而后面的东西是死活都出不来了,其也不会报错,这是因为out.println
在输出之前会检查一下是否关闭了,其检查的代码如下:private void ensureOpen() throws IOException {
if(response == null || closed)
throw new IOException("Stream closed");
else
return;
}response是不可能为空的,而closed只有在close的方法中才设为true,所以这个检查形同虚设。
而out.println("12121212");中的那些字符也许就被Tomcat吃掉了吧 :)
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.flush();
out.clearBuffer();
//out.close();
//OutputStream os = response.getOutputStream();
//os.write("this is a test".getBytes());
//os.close();
%>
a test line输出:12121212 a test line<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
//out.flush();
out.clearBuffer();
//out.close();
//OutputStream os = response.getOutputStream();
//os.write("this is a test".getBytes());
//os.close();
%>
a test line输出:a test line<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.flush();
out.clearBuffer();
out.close();
//OutputStream os = response.getOutputStream();
//os.write("this is a test".getBytes());
//os.close();
%>
a test line
输出:12121212
说明这个out.println("12121212");当时不马上输出的.out不具有自动行刷新的.你要out.flush();刷新该流的缓冲,才能马上输出.你后面再怎么操作它已经输出了.如果你不刷新缓冲流,后面又out.clearBuffer();清除了.所以也不输出了.也就被吃掉了.哈哈!如果out.close();它上面还是输出,就是下面不输出了,因为out已经关闭.我个人感觉out和os是一个对象.蛮有意思的.
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.flush();
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line
输出:12121212<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
//out.flush();
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line
输出:this is a test所以感觉是一个对象.
________________________________我也要哭了,为了这个帖子,我今天看了近一个下午的Tomcat源代码,
把看的结果都贴在10楼了,也被无视了....555~~躲在角落里绑个草人扎针去`````
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%
out.println("12121212");
out.clearBuffer();
out.close();
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close();
%>
a test line在我这里的输出结果为
this is a test但是控制台有异常输出
java.io.IOException: Stream closed
at org.apache.jasper.runtime.JspWriterImpl.ensureOpen(JspWriterImpl.java:203)
at org.apache.jasper.runtime.JspWriterImpl.clearBuffer(JspWriterImpl.java:159)
at org.apache.jsp.test.test_jsp._jspService(test_jsp.java:59)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:334)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:619)报错的地点在下面这个地方
OutputStream os = response.getOutputStream();
os.write("this is a test".getBytes());
os.close(); out.write("\r\n");
out.write("a test line\r\n");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer(); // 这个地方就是59行
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
}
}
}我得到的结论是
out.close();只是关闭了内部的PrintWrite的操作,并没有关闭输出流,
因为jsp在页面代码执行后,还要有后续的操作,所以OutputStream还是可以使用的。
而异常是因为out被关掉了,后面的2个out.write(); 虽然存在于缓冲区,但不能输出了,因为前面我已经os.close()掉了。
os.write("this is a test".getBytes());
os.close(); // 前面的out已经close掉了。下面还有两个输出,见后面的说明
// 异常的产生点实际上在这一句上。
out.write("\r\n");
out.write("a test line\r\n");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
}
}
}说明Aorg.apache.jasper.runtime.JspWriterImpl类,这个类实际上就是out对象,我们来看一下,它的write方法:// out.write仅是调用了这个方法
public void write(String s) throws IOException {
write(s, 0, s.length()); // 这个方法又调用了下面的一个
}public void write(String s, int off, int len) throws IOException {
ensureOpen(); // 这一句正是抛出异常的关键,方法见下
// 以下省略
....
}// 这个就是抛出异常的所在,在显式调用out.close(),而在close()中会将closed置为true
// 所以在接下来的out.write中就可抛异常
private void ensureOpen() throws IOException {
if(response == null || closed)
throw new IOException("Stream closed"); // 这句就是抛出异常点
else
return;
}
**********************************************************************
out.close();只是关闭了内部的PrintWrite的操作,并没有关闭输出流,
因为jsp在页面代码执行后,还要有后续的操作,所以OutputStream还是可以使用的。
—————————————————————————————————————————
out是一个JspWriter,是从response.getWriter()中产生的(具体的可看10楼的分析),而response.getOutputStream与JspWriter完全是不同的东西,一个是OutputStream,一个JspWriter。
所以它们任何一个的关闭与另一个是无关的。而有关的仅是 out 和 response.getWriter()。