《深入剖析tomcat》讀書筆記1

前言:

有比較宏觀的問題,如下(持續更新中):

1.能否用一句話說明tomcat或者一個java web服務器做的事情?

2.http請求是怎麼進入tomcat服務器的,即內部的調用序列是怎麼樣的?

3.tomcat或者jboss如何和我們的web框架整合?

……

也有微觀的問題,如下(持續更新中):

1.http1.1的新特性是什麼?你又是否知道爲什麼會新添加這些新特性?

2. servlet實現了的singleTreadModel接口,就是線程安全的嗎?

3.你也許知道filter是幹嘛的,但是你知道filter是在哪裏、何時、被哪個模塊調用執行的嗎?

……

深入剖析tomcat讀書筆記1涉及1-3章,本身並不涉及tomcat的任何源碼。

第一章-----一個簡單的web服務器

    介紹了簡單的實現web服務器的方法(對於靜態資源的處理,不涉及動態內容)。解析http報文得到請求的對象,處理請求對象得到結果,封裝結果返回相應對象。其實都是在用Java來實現一些字符串操作,通過字節流來承載內容。

Http協議

    主要簡單介紹了http協議,更詳細地介紹在

http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html

http請求組成:請求行、請求頭、實體。

請求行:請求方法----URI----協議/版本

請求頭:Accept、Accept-Charset、Host、User-Agent、Content-Length、Content-Type

實體:各個請求參數

http響應組成:狀態行、響應報頭、響應正文

狀態行:協議—狀態碼—描述

響應報頭:Location、Server、Content-Length、Content-Type、Last-Modified

Socket類

    Socket就是網絡連接的端點,有Socket和serverSocket兩種,前者爲客戶端建立,後者爲服務端建立。客戶端和服務端建立了socket鏈接,就可以進行通信。

socket通信是什麼?

    我認爲本質上就是一邊輸入數據,一邊輸出數據。在java裏面,就是用封裝的字節流來處理。

如何通信?

    發送數據方調用socket的getOutPutStream()方法,獲取OutputStream對象,用該OutputStream對象創建一個PrintWriter對象,調用PrintWriter的print()方法即可。接受數據方調用socket的getInputStream()方法,獲取InputStream對象,用該InputStream創建一個BufferReader,調用BufferReader的read()方法即可。

serverSocket

    serverSocket是服務端創建的,要等待來自客戶端的請求。當serverSocket接收到了連接請求後,它會創建一個socket處理與客戶端的通信。就是調用serverSocket.accept()方法。

serverSocket構造函數中有一個backlog屬性,表示連接的隊列的長度(而不是連接的數量)。“輸入連接指示(對連接的請求)的最大隊列長度被設置爲 backlog 參數。如果隊列滿時收到連接指示,則拒絕該連接。”

 

第二章-----一個簡單的servlet容器

   servlet容器主要可以處理動態內容。和Servlet技術並行的技術是cgi。和一個在騰訊工作的同學交流,騰訊web系統採用得就是cgi技術,後臺用C來實現。

Servlet是一套規範,要熟悉他,要參考在javax.servlet和java.servlet.http兩個包下的接口和類。最重要的接口就是servlet接口,有5個方法。

public void init(ServletConfig config)throws ServletException;
//當某個servlet被實例化後,servlet容器調用其init()方法進行初始化,比如設置數據庫鏈接、初始化默認值等等
public ServletConfig getServletConfig();
//取得的是web.xml文件中,<servlet><init-param>配置的參數
public void service(ServletRequestreq, ServletResponse res) throws ServletException,
IOException;
//當servlet的一個客戶端請求到達後,servlet容器就調用相應servlet的service()方法。參數類型分別爲ServletRequest和ServletResponse。前者包含http請求的信息,後者封裝servlet的響應信息。
public String getServletInfo();
//用Servlet類的getServletInfo方法獲取網頁的說明信息,GetServletInfo()方法是一個可選的方法,它提供有關servlet的信息,如作者、版本、版權。
public void destroy();
//在將servlet實例從服務中移出前,servlet容器會調用servlet實例的destory()方法。調用該方法,一般用來清理自身持有的資源,如內存、文件句柄和線程等等。

   如何實現一個簡單的servlet容器?

  作者給出了一個實例。思路如下:

1:等待HTTP請求。

2:構造一個ServletRequest對象和一個ServletResponse對象。

3:假如該請求需要一個靜態資源的話,調用StaticResourceProcessor實例的process方法,同時傳遞ServletRequest和ServletResponse對象。

4:假如該請求需要一個servlet的話,加載servlet類並調用servlet的service方法,同時傳遞ServletRequest和ServletResponse對象

5: 處理後結果,把封裝爲ServletResponse,返回。


第三章—連接器

     tomcat使用的servlet容器的名字是catalina,主要包含2個模塊:連接器(connector)和容器(container)。

連接器

    連接器作用:解析http請求頭(其實不只是可以接受http協議,還可以接受AJP協議,用於純web服務器比如apache和應用服務器比如tomcat的連接。關於web服務器和應用服務器的區別,可以自行谷歌之),使得servlet實例能夠獲取到請求頭、cookie等信息。

一個簡單的連接器實現

一個簡單的連接器由2個部分組成:httpConnector、httpProcessor。

httpConnector作用:

1.      等待http請求

2.      爲每個請求創建一個httpProcessor實例

3.      調用httpProcessor的process()方法

核心的代碼如下:

while (!stopped) {
      // Acceptthe next incoming connection from the server socket
      Socket socket = null;
      try {
        socket = serverSocket.accept();
      }
      catch (Exception e) {
        continue;
      }
      // Handthis socket off to an HttpProcessor
      HttpProcessor processor = new HttpProcessor(this);
      processor.process(socket);
    }

      httpProcessor作用:創建請求對象和響應對象。顯然,爲了servlet能夠處理,請求對象必須實現httpRequest接口,響應對象必須實現httpResponse接口。

     對於每一個傳入的http請求,完成4個操作:

1.  創建一個HttpRequest對象;

2.  創建一個HttpResponse對象;

3.  解析Http的請求行和請求頭,填充HttpRequest對象;

4.  將HttpRequest和HttpResponse傳遞給servlet的service()方法。

解析http請求步驟如下:

1.  讀取套接字的輸入流;

2.  解析請求行;

3.  解析請求頭;

4.  解析cookie;

5.  獲取參數

讀取套接字的輸入流僅需要調用servlet的getInputStream();解析請求行、請求頭、cookie

的parse方法都是按照http協議,比如如何從

“GET /my/app/servlet?username=mohe&password=123 HTTP /1.1”字符串中得到請求方法、URI、版本version。這些都是純字符串操作,大量運用了indexof()、subString()等方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章