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

  • 相关阅读:
    免费的视频、音频转文本
    Errors are values
    Codebase Refactoring (with help from Go)
    Golang中的坑二
    Cleaner, more elegant, and wrong(msdn blog)
    Cleaner, more elegant, and wrong(翻译)
    Cleaner, more elegant, and harder to recognize(翻译)
    vue控制父子组件渲染顺序
    computed 和 watch 组合使用,监听数据全局数据状态
    webstorm破解方法
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/13606228.html
Copyright © 2011-2022 走看看