zoukankan      html  css  js  c++  java
  • Tom_No_02 Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的解释

    上次在培训班学上网课的时候就发现了这个问题,一直没有解决,昨天又碰到了,2-3小时也未能发现点端倪,今早又仔细缕了下,让我看了他的秘密

    1.Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的问题描述

    public class ServletProcessor {
        public void process(HttpRequest request,HttpResponse response){
    ...
            try {
                servlet = (Servlet) myClass.newInstance();
                HttpRequestFacade requestFacade = new HttpRequestFacade(request);
                HttpResponseFacade responseFacade = new HttpResponseFacade(response);
                servlet.service(requestFacade, responseFacade);//先调用servlet代码
                ((HttpResponse) response).finishResponse();//后执行完成response
            }
            catch (Exception e) {
                System.out.println(e.toString());
            }
            catch (Throwable e) {
                System.out.println(e.toString());
            }
        }
    }
    servlet.service(requestFacade, responseFacade);//先调用servlet代码
    public class PrimitiveServlet implements Servlet {
    
      public void init(ServletConfig config) throws ServletException {
        System.out.println("init");
      }
      public void service(ServletRequest request, ServletResponse response)
        throws ServletException, IOException {
        System.out.println("from service");
        PrintWriter out = response.getWriter();//这里是关键稍后分析
        out.println("Hello. Roses are red.");//打印
        out.print("Violets are blue.");
      }
      public void destroy() {
        System.out.println("destroy");
      }
      public String getServletInfo() {
        return null;
      }
      public ServletConfig getServletConfig() {
        return null;
      }
    
    }
    ((HttpResponse) response).finishResponse();//后执行完成response

        public void finishResponse()throws IOException{
             sendHeaders();
            // Flush and close the appropriate output mechanism
            if(writer !=null){
                writer.flush();
                System.out.println("finishResponse writer.flush");
                writer.close();
            }
        }
    
    protected void sendHeaders() throws IOException{
            if(isCommitted())
                return;
            OutputStreamWriter osr=null;
            try{
                osr=new OutputStreamWriter(getStream(),getCharacterEncoding());
            }catch (UnsupportedEncodingException e) {
                osr = new OutputStreamWriter(getStream());
            }
            final PrintWriter outputWriter = new PrintWriter(osr);
            outputWriter.print(this.getProtocol());
            outputWriter.print(" ");
            outputWriter.print(status);
            if(message!=null){
                outputWriter.print(" ");
                outputWriter.print(message); //OK 状态描述
            }
            outputWriter.print("
    ");
            if (getContentType()!=null){
                outputWriter.print("Content-Type: " + getContentType() + "
    ");
            }
            if(getContentLength()>=0){
                outputWriter.print("Content-Length: " + getContentLength() + "
    ");
            }
            synchronized (headers){
                    Iterator items=headers.keySet().iterator();
                    while(items.hasNext()){
                        String name=(String)items.next();
                        ArrayList list =(ArrayList) headers.get(name);
                        Iterator iterator = list.iterator();
                        while (iterator.hasNext()){
                            String value = (String)iterator.next();
                            outputWriter.print(name);
                            outputWriter.print(": ");
                            outputWriter.print(value);
                            outputWriter.print("
    ");
                        }
                    }
            }
            synchronized (cookies){
                Iterator items=cookies.iterator();
                while(items.hasNext()){
                    Cookie cookie=(Cookie)items.next();
                    outputWriter.print(CookieTools.getCookieHeaderName(cookie));
                    outputWriter.print(": ");
                    outputWriter.print(CookieTools.getCookieHeaderValue(cookie));
                    outputWriter.print("
    ");
                }
            }
            // Send a terminating blank line to mark the end of the headers
            outputWriter.print("
    ");
            outputWriter.flush();
            System.out.println("给response的header发送完成");
    
            committed = true;
        }

     问题描述完毕

    2.突破口,在sendHeader中的outputWriter与servlet中的 PrintWriter out = response.getWriter();不是一个东西

    先说sentHader中的

     try{
                osr=new OutputStreamWriter(getStream(),getCharacterEncoding());
            }catch (UnsupportedEncodingException e) {
                osr = new OutputStreamWriter(getStream());
            }
            final PrintWriter outputWriter = new PrintWriter(osr);
            outputWriter.print(this.getProtocol());
            outputWriter.print(" ");
            outputWriter.print(status);
    其中
        public OutputStream getStream(){
            return this.output;
        }
    构造方法
        public HttpResponse(OutputStream output)
        {
            this.output=output;
        }
    他被调用位置见图片

    小结:sendheader中的PrintWriter就是使用了outputSteam做为底层的输出流

    3.servlet中的 PrintWriter out = response.getWriter()的包裹关系

        public PrintWriter getWriter() throws IOException{
            ResponseStream newStream = new ResponseStream(this);
            newStream.setCommit(false);
            OutputStreamWriter osr=
                    new OutputStreamWriter(newStream,getCharacterEncoding());
            writer=new ResponseWriter(osr);
            return  writer;
        }

    见解释图

    说明:

    1.servlet中getWrter得到是ResponseWriter,调用responseWriter的frint("")方法,通过流的调用,最后底层流是ResponseStream,调用其方法为writer(...)

      writer方法是将"Rode Are Red" 字符串写入到HttpResponse的成员变量buff中

    2.在调用close的时候,最后调用ResponseStream的close方法,接着在flushbuffer中才最终叫内容"Rode Are Red",发送给浏览器

    几张debugger图

    atzhang

  • 相关阅读:
    VB Open 函数详解 打开、关闭、读、写文件
    VB程序设计中Combobox的取值问题
    vb中typename函数
    VB.NET Event RaiseEvent用处
    通过关键字Event定义用户自己的事件
    [转]如何在注册表中进行查找
    [转]ADT中通过DDMS导入文件出错ddms transfer error: Read-only file system,Failed to push selection: Read-only file system
    [转]在eclipse打开的android虚拟手机,打开File Explorer,下面是空的没有data、mnt、system三个文件
    [转]Android开发过程中遇到的问题
    [转]如何解决android模拟器慢的问题
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/13606228.html
Copyright © 2011-2022 走看看