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

  • 相关阅读:
    uoj#207 共价大爷游长沙
    bzoj4006 [JLOI2015]管道连接
    bzoj2595 [Wc2008]游览计划
    uoj#300.【CTSC2017】吉夫特
    bzoj2565 最长双回文串
    bzoj2342 [Shoi2011]双倍回文
    bzoj3676 [Apio2014]回文串
    [转载]物理大神的八卦完整版——大爱物理
    低层次数论书籍大杂烩
    控制论课题
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/13606228.html
Copyright © 2011-2022 走看看