亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

How Tomcat Works(四)

系統(tǒng) 2593 0

Servlet容器有兩個(gè)主要的模塊,即連接器(connector)與容器(container),本文接下來創(chuàng)建一個(gè)連接器來增強(qiáng)前面文章中的應(yīng)用程序的功能,以一種更優(yōu)雅的方式來創(chuàng)建request對(duì)象和response對(duì)象;為了兼容Servlet 2.3和2.4,連接器這里創(chuàng)建的是javax.servlet.http.HttpServletRequest對(duì)象和javax.servlet.http.HttpServletResponse對(duì)象(servlet對(duì)象類型可以是實(shí)現(xiàn)javax.servlet.Servlet接口或繼承自javax.servlet.GenericServlet類或javax.servlet.http.HttpServlet類)。

在本文的應(yīng)用程序中,連接器會(huì)解析http請(qǐng)求頭、cookies和請(qǐng)求參數(shù)等;同時(shí)修改了Response類的getWriter()方法,使其工作得更好。

本文首先要介紹一下在servlet容器中是怎么實(shí)現(xiàn)錯(cuò)誤消息國際化的,這里主要是StringManager類實(shí)現(xiàn)的功能

Tomcat是將錯(cuò)誤消息存儲(chǔ)在properties文件中,便于讀取和編輯;可是由于 tomcat的類特別多,將所有類使用的錯(cuò)誤消息都存儲(chǔ)在同一個(gè)properties文件中將會(huì)造成維護(hù)的困難;所以tomcat的處理方式是將properties劃分在不同的包中,每個(gè)properties文件都是用StringManager類的一個(gè)實(shí)例來處理,這樣在tomcat運(yùn)行時(shí),會(huì)產(chǎn)生StringManager類的多個(gè)實(shí)例;同一個(gè)包里面的類共享一個(gè)StringManager類的實(shí)例(這里采用單例模式);這些不同包用到的的StringManager類的實(shí)例存儲(chǔ)在一個(gè)hashtable容器中,以包名作為key存儲(chǔ)StringManager類的實(shí)例

      
        public
      
      
        class
      
      
         StringManager {

    
      
      
        /**
      
      
        
     * The ResourceBundle for this StringManager.
     
      
      
        */
      
      
        private
      
      
         ResourceBundle bundle;

    
      
      
        /**
      
      
        
     * Creates a new StringManager for a given package. This is a
     * private method and all access to it is arbitrated by the
     * static getManager method call so that only one StringManager
     * per package will be created.
     *
     * 
      
      
        @param
      
      
         packageName Name of package to create StringManager for.
     
      
      
        */
      
      
        private
      
      
         StringManager(String packageName) {
    String bundleName 
      
      = packageName + ".LocalStrings"
      
        ;
    bundle 
      
      =
      
         ResourceBundle.getBundle(bundleName);
    }

    
      
      
        /**
      
      
        
     * Get a string from the underlying resource bundle.
     *
     * 
      
      
        @param
      
      
         key 
     
      
      
        */
      
      
        public
      
      
         String getString(String key) {
        
      
      
        if
      
       (key == 
      
        null
      
      
        ) {
            String msg 
      
      = "key is null"
      
        ;

            
      
      
        throw
      
      
        new
      
      
         NullPointerException(msg);
        }

        String str 
      
      = 
      
        null
      
      
        ;

        
      
      
        try
      
      
         {
        str 
      
      =
      
         bundle.getString(key);
        } 
      
      
        catch
      
      
         (MissingResourceException mre) {
            str 
      
      = "Cannot find message associated with key '" + key + "'"
      
        ;
        }

        
      
      
        return
      
      
         str;
    }
   
      
      
        //
      
      
         --------------------------------------------------------------
    
      
      
        //
      
      
         STATIC SUPPORT METHODS
    
      
      
        //
      
      
         --------------------------------------------------------------
      
      
        private
      
      
        static
      
       Hashtable managers = 
      
        new
      
      
         Hashtable();

    
      
      
        /**
      
      
        
     * Get the StringManager for a particular package. If a manager for
     * a package already exists, it will be reused, else a new
     * StringManager will be created and returned.
     *
     * 
      
      
        @param
      
      
         packageName
     
      
      
        */
      
      
        public
      
      
        synchronized
      
      
        static
      
      
         StringManager getManager(String packageName) {
    StringManager mgr 
      
      =
      
         (StringManager)managers.get(packageName);
    
      
      
        if
      
       (mgr == 
      
        null
      
      
        ) {
        mgr 
      
      = 
      
        new
      
      
         StringManager(packageName);
        managers.put(packageName, mgr);
    }
    
      
      
        return
      
      
         mgr;
    }
}
      
    

下面我們來分析連接器是怎樣實(shí)現(xiàn)的:

      
        public
      
      
        class
      
       HttpConnector 
      
        implements
      
      
         Runnable {

  
      
      
        boolean
      
      
         stopped;
  
      
      
        private
      
       String scheme = "http"
      
        ;

  
      
      
        public
      
      
         String getScheme() {
    
      
      
        return
      
      
         scheme;
  }

  
      
      
        public
      
      
        void
      
      
         run() {
    ServerSocket serverSocket 
      
      = 
      
        null
      
      
        ;
    
      
      
        int
      
       port = 8080
      
        ;
    
      
      
        try
      
      
         {
      serverSocket 
      
      =  
      
        new
      
       ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"
      
        ));
    }
    
      
      
        catch
      
      
         (IOException e) {
      e.printStackTrace();
      System.exit(
      
      1
      
        );
    }
    
      
      
        while
      
       (!
      
        stopped) {
      
      
      
        //
      
      
         Accept the next incoming connection from the server socket
      
      
      Socket socket = 
      
        null
      
      
        ;
      
      
      
        try
      
      
         {
        socket 
      
      =
      
         serverSocket.accept();
      }
      
      
      
        catch
      
      
         (Exception e) {
        
      
      
        continue
      
      
        ;
      }
      
      
      
        //
      
      
         Hand this socket off to an HttpProcessor
      
      
      HttpProcessor processor = 
      
        new
      
       HttpProcessor(
      
        this
      
      
        );
      processor.process(socket);
    }
  }

  
      
      
        public
      
      
        void
      
      
         start() {
    Thread thread 
      
      = 
      
        new
      
       Thread(
      
        this
      
      
        );
    thread.start();
  }
}
      
    

我們從HttpConnector連接器的實(shí)現(xiàn)可以看到,該連接器負(fù)責(zé)監(jiān)聽客戶端請(qǐng)求,當(dāng)監(jiān)聽到客戶端請(qǐng)求時(shí),將獲取的socket對(duì)象交給HttpProcessor對(duì)象的process()方法處理

我們接下來分析HttpProcessor類的實(shí)現(xiàn):

      
        /*
      
      
         this class used to be called HttpServer 
      
      
        */
      
      
        public
      
      
        class
      
      
         HttpProcessor {

  
      
      
        public
      
      
         HttpProcessor(HttpConnector connector) {
    
      
      
        this
      
      .connector =
      
         connector;
  }
  
      
      
        /**
      
      
        
   * The HttpConnector with which this processor is associated.
   
      
      
        */
      
      
        private
      
       HttpConnector connector = 
      
        null
      
      
        ;
  
      
      
        private
      
      
         HttpRequest request;
        
private HttpResponse response; public void process(Socket socket) { SocketInputStream input = null ; OutputStream output = null ; try {
// 包裝為SocketInputStream對(duì)象 input
= new SocketInputStream(socket.getInputStream(), 2048 ); output = socket.getOutputStream(); // create HttpRequest object and parse request = new HttpRequest(input); // create HttpResponse object response = new HttpResponse(output); response.setRequest(request); response.setHeader( "Server", "Pyrmont Servlet Container" ); // 解析請(qǐng)求行 parseRequest(input, output);
// 解析請(qǐng)求頭 parseHeaders(input);
// check if this is a request for a servlet or a static resource // a request for a servlet begins with "/servlet/" if (request.getRequestURI().startsWith("/servlet/" )) { ServletProcessor processor = new ServletProcessor(); processor.process(request, response); } else { StaticResourceProcessor processor = new StaticResourceProcessor(); processor.process(request, response); } // Close the socket socket.close(); // no shutdown for this application } catch (Exception e) { e.printStackTrace(); } }

上面的方法中獲取socket對(duì)象的輸入流與輸出流分別創(chuàng)建Request對(duì)象與Response對(duì)象,然后解析http請(qǐng)求行與請(qǐng)求頭(并填充到Request對(duì)象的相應(yīng)屬性),最后分發(fā)給處理器處理

接下來的Request對(duì)象實(shí)現(xiàn)了javax.servlet.http.HttpServletRequest接口,主要是提供一些設(shè)置相關(guān)請(qǐng)求參數(shù)的方法和獲取相關(guān)請(qǐng)求參數(shù)的方法

http請(qǐng)求頭、cookies和請(qǐng)求參數(shù)等信息分別存儲(chǔ)在如下成員變量中

protected ArrayList cookies = new ArrayList();

protected HashMap headers = new HashMap();

protected ParameterMap parameters = null;

需要注意的是protected void parseParameters()方法只需執(zhí)行一次,該方法是用來初始化ParameterMap parameters成員變量,方法如下

      
        /**
      
      
        
   * Parse the parameters of this request, if it has not already occurred.
   * If parameters are present in both the query string and the request
   * content, they are merged.
   
      
      
        */
      
      
        protected
      
      
        void
      
      
         parseParameters() {
    
      
      
        if
      
      
         (parsed)
      
      
      
        return
      
      
        ;
    ParameterMap results 
      
      =
      
         parameters;
    
      
      
        if
      
       (results == 
      
        null
      
      
        )
      results 
      
      = 
      
        new
      
      
         ParameterMap();
    results.setLocked(
      
      
        false
      
      
        );
    String encoding 
      
      =
      
         getCharacterEncoding();
    
      
      
        if
      
       (encoding == 
      
        null
      
      
        )
      encoding 
      
      = "ISO-8859-1"
      
        ;

    
      
      
        //
      
      
         Parse any parameters specified in the query string
      
      
    String queryString =
      
         getQueryString();
    
      
      
        try
      
      
         {
      RequestUtil.parseParameters(results, queryString, encoding);
    }
    
      
      
        catch
      
      
         (UnsupportedEncodingException e) {
      ;
    }

    
      
      
        //
      
      
         Parse any parameters specified in the input stream
      
      
    String contentType =
      
         getContentType();
    
      
      
        if
      
       (contentType == 
      
        null
      
      
        )
      contentType 
      
      = ""
      
        ;
    
      
      
        int
      
       semicolon = contentType.indexOf(';'
      
        );
    
      
      
        if
      
       (semicolon >= 0
      
        ) {
      contentType 
      
      = contentType.substring(0
      
        , semicolon).trim();
    }
    
      
      
        else
      
      
         {
      contentType 
      
      =
      
         contentType.trim();
    }
    
      
      
        if
      
       ("POST".equals(getMethod()) && (getContentLength() > 0
      
        )
      
      
      && "application/x-www-form-urlencoded"
      
        .equals(contentType)) {
      
      
      
        try
      
      
         {
        
      
      
        int
      
       max =
      
         getContentLength();
        
      
      
        int
      
       len = 0
      
        ;
        
      
      
        byte
      
       buf[] = 
      
        new
      
      
        byte
      
      
        [getContentLength()];
        ServletInputStream is 
      
      =
      
         getInputStream();
        
      
      
        while
      
       (len <
      
         max) {
          
      
      
        int
      
       next = is.read(buf, len, max -
      
         len);
          
      
      
        if
      
       (next < 0
      
         ) {
            
      
      
        break
      
      
        ;
          }
          len 
      
      +=
      
         next;
        }
        is.close();
        
      
      
        if
      
       (len <
      
         max) {
          
      
      
        throw
      
      
        new
      
       RuntimeException("Content length mismatch"
      
        );
        }
        RequestUtil.parseParameters(results, buf, encoding);
      }
      
      
      
        catch
      
      
         (UnsupportedEncodingException ue) {
        ;
      }
      
      
      
        catch
      
      
         (IOException e) {
        
      
      
        throw
      
      
        new
      
       RuntimeException("Content read fail"
      
        );
      }
    }

    
      
      
        //
      
      
         Store the final results
      
      
    results.setLocked(
      
        true
      
      
        );
    parsed 
      
      = 
      
        true
      
      
        ;
    parameters 
      
      =
      
         results;
  }
      
    

我就不明白,該方法為什么不采取同步鎖關(guān)鍵字?難道是對(duì)初始化ParameterMap parameters成員變量次數(shù)沒有硬性要求?

上面方法中的ParameterMap對(duì)象,繼承自HashMap,采用boolean locked = false成員變量設(shè)置寫入的鎖(這玩意也有問題)

      
        public
      
      
        final
      
      
        class
      
       ParameterMap 
      
        extends
      
      
         HashMap {


    
      
      
        //
      
      
         ----------------------------------------------------------- Constructors
      
      
        /**
      
      
        
     * Construct a new, empty map with the default initial capacity and
     * load factor.
     
      
      
        */
      
      
        public
      
      
         ParameterMap() {

        
      
      
        super
      
      
        ();

    }


    
      
      
        /**
      
      
        
     * Construct a new, empty map with the specified initial capacity and
     * default load factor.
     *
     * 
      
      
        @param
      
      
         initialCapacity The initial capacity of this map
     
      
      
        */
      
      
        public
      
       ParameterMap(
      
        int
      
      
         initialCapacity) {

        
      
      
        super
      
      
        (initialCapacity);

    }


    
      
      
        /**
      
      
        
     * Construct a new, empty map with the specified initial capacity and
     * load factor.
     *
     * 
      
      
        @param
      
      
         initialCapacity The initial capacity of this map
     * 
      
      
        @param
      
      
         loadFactor The load factor of this map
     
      
      
        */
      
      
        public
      
       ParameterMap(
      
        int
      
       initialCapacity, 
      
        float
      
      
         loadFactor) {

        
      
      
        super
      
      
        (initialCapacity, loadFactor);

    }


    
      
      
        /**
      
      
        
     * Construct a new map with the same mappings as the given map.
     *
     * 
      
      
        @param
      
      
         map Map whose contents are dupliated in the new map
     
      
      
        */
      
      
        public
      
      
         ParameterMap(Map map) {

        
      
      
        super
      
      
        (map);

    }


    
      
      
        //
      
      
         ------------------------------------------------------------- Properties
      
      
        /**
      
      
        
     * The current lock state of this parameter map.
     
      
      
        */
      
      
        private
      
      
        boolean
      
       locked = 
      
        false
      
      
        ;


    
      
      
        /**
      
      
        
     * Return the locked state of this parameter map.
     
      
      
        */
      
      
        public
      
      
        boolean
      
      
         isLocked() {

        
      
      
        return
      
       (
      
        this
      
      
        .locked);

    }


    
      
      
        /**
      
      
        
     * Set the locked state of this parameter map.
     *
     * 
      
      
        @param
      
      
         locked The new locked state
     
      
      
        */
      
      
        public
      
      
        void
      
       setLocked(
      
        boolean
      
      
         locked) {

        
      
      
        this
      
      .locked =
      
         locked;

    }


    
      
      
        /**
      
      
        
     * The string manager for this package.
     
      
      
        */
      
      
        private
      
      
        static
      
      
        final
      
       StringManager sm =
      
        
        StringManager.getManager(
      
      "org.apache.catalina.util"
      
        );


    
      
      
        //
      
      
         --------------------------------------------------------- Public Methods
      
      
        /**
      
      
        
     * Remove all mappings from this map.
     *
     * 
      
      
        @exception
      
      
         IllegalStateException if this map is currently locked
     
      
      
        */
      
      
        public
      
      
        void
      
      
         clear() {

        
      
      
        if
      
      
         (locked)
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (sm.getString(
      
      "parameterMap.locked"
      
        ));
        
      
      
        super
      
      
        .clear();

    }


    
      
      
        /**
      
      
        
     * Associate the specified value with the specified key in this map.  If
     * the map previously contained a mapping for this key, the old value is
     * replaced.
     *
     * 
      
      
        @param
      
      
         key Key with which the specified value is to be associated
     * 
      
      
        @param
      
      
         value Value to be associated with the specified key
     *
     * 
      
      
        @return
      
      
         The previous value associated with the specified key, or
     *  <code>null</code> if there was no mapping for key
     *
     * 
      
      
        @exception
      
      
         IllegalStateException if this map is currently locked
     
      
      
        */
      
      
        public
      
      
         Object put(Object key, Object value) {

        
      
      
        if
      
      
         (locked)
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (sm.getString(
      
      "parameterMap.locked"
      
        ));
        
      
      
        return
      
       (
      
        super
      
      
        .put(key, value));

    }


    
      
      
        /**
      
      
        
     * Copy all of the mappings from the specified map to this one.  These
     * mappings replace any mappings that this map had for any of the keys
     * currently in the specified Map.
     *
     * 
      
      
        @param
      
      
         map Mappings to be stored into this map
     *
     * 
      
      
        @exception
      
      
         IllegalStateException if this map is currently locked
     
      
      
        */
      
      
        public
      
      
        void
      
      
         putAll(Map map) {

        
      
      
        if
      
      
         (locked)
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (sm.getString(
      
      "parameterMap.locked"
      
        ));
        
      
      
        super
      
      
        .putAll(map);

    }


    
      
      
        /**
      
      
        
     * Remove the mapping for this key from the map if present.
     *
     * 
      
      
        @param
      
      
         key Key whose mapping is to be removed from the map
     *
     * 
      
      
        @return
      
      
         The previous value associated with the specified key, or
     *  <code>null</code> if there was no mapping for that key
     *
     * 
      
      
        @exception
      
      
         IllegalStateException if this map is currently locked
     
      
      
        */
      
      
        public
      
      
         Object remove(Object key) {

        
      
      
        if
      
      
         (locked)
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (sm.getString(
      
      "parameterMap.locked"
      
        ));
        
      
      
        return
      
       (
      
        super
      
      
        .remove(key));

    }


}
      
    

同樣Response對(duì)象實(shí)現(xiàn)了javax.servlet.http.HttpServletResponse接口

這里改寫了前面文章中的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;
  }
      
    

---------------------------------------------------------------------------?

本系列How Tomcat Works系本人原創(chuàng)?

轉(zhuǎn)載請(qǐng)注明出處 博客園 刺猬的溫馴?

本人郵箱: chenying998179 # 163.com ( #改為@

本文鏈接 http://www.cnblogs.com/chenying99/p/3231639.html

How Tomcat Works(四)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 午夜影院网页 | 一级特黄牲大片免费视频 | 2022国产成人综合精品 | 国产一区二区免费 | 亚洲激情视频网站 | 午夜影院普通 | 久草视频在线播放 | 狠狠色噜噜狠狠狠888奇米 | 尹人香蕉99久久综合网站 | 久久99国产精一区二区三区 | 亚洲黄色自拍 | 久久久久久久久久免观看 | 五月天亚洲婷婷 | 日本高清无吗免费播放 | 国产成人精品一区 | 久久99久久 | 老司机精品视频个人在观看 | 欧美区国产区 | 夜夜夜夜夜夜爽噜噜噜噜噜噜 | 老司机久久精品视频 | 亚洲天堂资源 | 在线观看深夜观看网站免费 | 亚洲综合精品成人啪啪 | 日本在线一级 | 久久99九九99九九精品 | 私人小影院在线 观看 | 久久成人亚洲香蕉草草 | 男人草女人的视频 | 久久这里只有精品免费的 | 久久这里只有精品18 | 日本一区二区三区精品 | 日日摸夜夜嗷嗷叫日日拍 | 亚洲欧美另类久久久精品能播放的 | 中文字幕av在线 | 成人国内精品久久久久影 | 亚洲美女黄视频 | 黄色伊人 | 四虎地址8848jia | 人人干在线观看 | 欧美另类高清xxxxx | 啪啪综合网 |