大家猜一下结果,再去测试,很奇怪的事情。也许有些内幕没有搞清楚
<%@ 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屏幕输出啥?

解决方案 »

  1.   


    <%@ 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的异常...
      

  2.   


    <%@ 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里面只要有东西就会被显示出来....
      

  3.   

    debug的话发现,当执行到out.pringln("12121212");的时候页面中所有的outputBuffer和outputStream都被放入了12121212的内容....
    无论是outputStream还是writer....
      

  4.   


    <%@ 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不能输出了...
      

  5.   

    我最关心的是
      out.close();
      OutputStream os = response.getOutputStream();明明已经关闭了,怎么还能输出呢?难道??? 搞不懂哦!!
      

  6.   

    4楼的测试里,所有outputBuffer都被装入了12121212.....在5楼的时候我在os.write( "this is a test".getBytes() );这句前加上断点,debug里面发现:response里有一个属性outputBuffer,其当时id=1568
    而属性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.....
      

  7.   

    内置的out对象是一个JspWriter对象,也就是Writer对象,
    而response.getOutputStream是一个OutputStream对象
    两个都是不同的东西,根本不会受到任何影响的。就算不采用response.getOutputStream而采用response.getWriter()
    得到的Writer对象,与out中的Writer也是对象不一样的,可以通过
    Writer os = response.getWriter();
    System.out.println(out == os);
    得知。实际上out对象是在Servlet容器初始化的时候就产生了,将其关掉以后后面
    所有的页面都不会输出了。而response中的Writer只是在请求/响应阶段产
    生的,每一个请求/响应都会产生一次对象的。
      

  8.   

    回8楼:所以我猜测这两个对象虽然不一样,但是使用了同一个outputBuffer来装东西....
      

  9.   

    呵呵,抱歉~~上面有许多不对的地方。请管理员将8楼的帖子删除。
    更正一下: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吃掉了吧 :)
      

  10.   

    也许是java在编译Jsp时做了小动作吧...我在断点里看见它们用一个outputBuffer...
      

  11.   

    <%@ 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 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是一个对象.蛮有意思的.
      

  12.   

    回12楼,不是一个对象,而是两个对象用了同一个buffer来放东西...我哭...怎么我7楼的回复被无视了....绑个草人扎针去~~~``
      

  13.   

    <%@ 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<%@ 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所以感觉是一个对象.
      

  14.   

    同一个buffer看来是肯定的,但上面的out不关闭,下面的os就不能得到,为什么呢?
      

  15.   

    13楼   我哭...怎么我7楼的回复被无视了....绑个草人扎针去~~~``
    ________________________________我也要哭了,为了这个帖子,我今天看了近一个下午的Tomcat源代码,
    把看的结果都贴在10楼了,也被无视了....555~~躲在角落里绑个草人扎针去`````
      

  16.   

    火龙果辛苦了。呵呵,这个代码
    <%@ 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()掉了。
      

  17.   

    这个代码为什么会报错,原因就在于(见下面的注释)  OutputStream os = response.getOutputStream();
      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()。