深刻拆解Tomcat & Jetty-學習筆記(1)模塊一之必備基礎

模塊一 必備基礎

01 HTTP協議必知必會的知識

http請求過程

  1. 用戶經過瀏覽器進行了一個操做,好比輸入網址並回車,或者是點擊連接,接着瀏覽器獲取了這個事件。
  2. 瀏覽器向服務端發出 TCP 鏈接請求。
  3. 服務程序接受瀏覽器的鏈接請求,並通過 TCP 三次握手創建鏈接。
  4. 瀏覽器將請求數據打包成一個 HTTP 協議格式的數據包。
  5. 瀏覽器將該數據包推入網絡,數據包通過網絡傳輸,最終達到端服務程序。
  6. 服務端程序拿到這個數據包後,一樣以 HTTP 協議格式解包,獲取到客戶端的意圖。
  7. 得知客戶端意圖後進行處理,好比提供靜態文件或者調用服務端程序得到動態結果。
  8. 服務器將響應結果(多是 HTML 或者圖片等)按照 HTTP 協議格式打包。
    1. 服務器將響應數據包推入網絡,數據包通過網絡傳輸最終達到到瀏覽器。
  9. 瀏覽器拿到數據包後,以 HTTP 協議的格式解包,而後解析數據,假設這裏的數據是 HTML。
  10. 瀏覽器將 HTML 文件展現在頁面上。
http請求響應實例

請求:請求行,請求頭,請求體 響應:狀態行,響應報文,報文主體java

cookie和session

Cookie 本質上就是一份存儲在用戶本地的文件,裏面包含了每次請求中都須要傳遞的信息程序員

Session 能夠理解爲服務器端開闢的存儲空間,裏面保存了用戶的狀態web

當用戶請求到來時,服務端能夠把用戶的請求和用戶的 Session 對應起來。那麼 Session 是怎麼和請求對應起來的呢?答案是經過 Cookie,瀏覽器在 Cookie 中填充了一個 Session ID 之類的字段用來標識請求。spring

關於restful風格的理解

將網絡上的信息實體看做是資源,能夠是圖片、文件、一個服務...資源用URI統一標識,URI中沒有動詞哦,這是由於它是資源的標識,那怎麼操做這些資源呢,因而定義一些動做:GET、POST、PUT和DELETE。經過URI+動做來操做一個資源。瀏覽器

關於Http無狀態的請求的理解

所謂的無狀態說的是,爲了完成一個操做,請求裏包含了全部信息,你能夠理解爲服務端不須要保存請求的狀態,也就是不須要保存session,沒有session的好處是帶來了服務端良好的可伸縮性,方便failover,請求被LB轉到不一樣的server實例上沒有差異。從這個角度看,正是有了REST架構風格的指導,纔有了HTTP的無狀態特性,順便提一下,REST和HTTP1.1出自同一人之手。可是理想是豐滿的,現實是骨感的,爲了方便開發,大多數複雜的Web應用不得不在服務端保存Session。爲了儘可能減小Session帶來的弊端,每每將Session集中存儲到Redis上,而不是直接存儲在server實例上。服務器

關於http長鏈接的理解以及1.0和1.1和2.0的區別

在 HTTP/1.0 時期,每次 HTTP 請求都會建立一個新的 TCP 鏈接,請求完成後以後這個 TCP 鏈接就會被關閉。這種通訊模式的效率不高 HTTP/1.1 中,引入了 HTTP 長鏈接的概念,使用長鏈接的 HTTP 協議,會在響應頭加入 Connection:keep-alive。這樣當瀏覽器完成一次請求後,瀏覽器和服務器之間的 TCP 鏈接不會關閉,再次訪問這個服務器上的網頁時,瀏覽器會繼續使用這一條已經創建的鏈接,也就是說兩個請求可能共用一個 TCP 鏈接。 HTTP/1.1中的長鏈接依然沒有解決 head of line blocking 的問題,後面的鏈接必須等待前面的返回了纔可以發送,這個問題直到HTTP/2.0採起二進制分幀編碼方式才完全解決。restful

02.servlet規範和servlet容器

servlet和servlet容器的關係

Servlet 本質上是一個接口,實現了 Servlet 接口的業務類也叫 Servlet。Servlet 接口實際上是 Servlet 容器跟具體 Servlet 業務類之間的接口。Servlet 接口跟 Servlet 容器這一整套規範叫做 Servlet 規範,而 Servlet 規範使得程序員能夠專一業務邏輯的開發,同時 Servlet 規範也給開發者提供了擴展的機制 Filter 和 Listener。cookie

public interface Servlet {
    void init(ServletConfig config) throws ServletException;
    
    ServletConfig getServletConfig();
    
    void service(ServletRequest req, ServletResponse res)throws ServletException, IOException; String getServletInfo();
    
    void destroy();
}
複製代碼
Servlet容器工程流程

  1. 當客戶請求某個資源時,HTTP 服務器會用一個 ServletRequest 對象把客戶的請求信息封裝起來
  2. 而後調用 Servlet 容器的 service 方法,Servlet 容器拿到請求後,根據請求的 URL 和 Servlet 的映射關係,找到相應的 Servlet
  3. 若是 Servlet 尚未被加載,就用反射機制建立這個 Servlet,並調用 Servlet 的 init 方法來完成初始化
  4. 接着調用 Servlet 的 service 方法來處理請求,把 ServletResponse 對象返回給 HTTP 服務器,HTTP 服務器會把響應發送給客戶端。
什麼是ServletContext

Servlet 規範裏定義了 ServletContext 這個接口來對應一個 Web 應用。Web 應用部署好後,Servlet 容器在啓動時會加載 Web 應用,併爲每一個 Web 應用建立惟一的 ServletContext 對象。你能夠把 ServletContext 當作是一個全局對象,一個 Web 應用可能有多個 Servlet,這些 Servlet 能夠經過全局的 ServletContext 來共享數據,這些數據包括 Web 應用的初始化參數、Web 應用目錄下的文件資源等。因爲 ServletContext 持有全部 Servlet 實例,你還能夠經過它來實現 Servlet 請求的轉發。網絡

什麼是Filter

Filter 是過濾器,這個接口容許你對請求和響應作一些統一的定製化處理,好比你能夠根據請求的頻率來限制訪問,或者根據國家地區的不一樣來修改響應內容。過濾器的工做原理是這樣的:Web 應用部署完成後,Servlet 容器須要實例化 Filter 並把 Filter 連接成一個 FilterChain。當請求進來時,獲取第一個 Filter 並調用 doFilter 方法,doFilter 方法負責調用這個 FilterChain 中的下一個 Filter。session

什麼是Listener

Listener 是監聽器,這是另外一種擴展機制。當 Web 應用在 Servlet 容器中運行時,Servlet 容器內部會不斷的發生各類事件,如 Web 應用的啓動和中止、用戶請求到達等。 Servlet 容器提供了一些默認的監聽器來監聽這些事件,當事件發生時,Servlet 容器會負責調用監聽器的方法。固然,你能夠定義本身的監聽器去監聽你感興趣的事件,將監聽器配置在web.xml中。好比 Spring 就實現了本身的監聽器,來監聽 ServletContext 的啓動事件,目的是當 Servlet 容器啓動時,建立並初始化全局的 Spring 容器。

Filter和Listener以及(intercepter )攔截器的關係

1.Filter是Servlet規範的一部分,是Servlet容器Tomcat實現的。 2.Intercepter是Spring發明的。 3.它們的執行順序是: Filter.doFilter(); HandlerInterceptor.preHandle(); Controller; HandlerInterceptor.postHandle(); DispatcherServlet 渲染視圖 HandlerInterceptor.afterCompletion(); Filter.doFilter(); Servlet方法返回;

Filter 是干預過程的,它是過程的一部分,是基於過程行爲的。 Listener 是基於狀態的,任何行爲改變同一個狀態,觸發的事件是一致的。

servlet容器和Spring容器和SpringMVC容器之間的關係

Servlet容器,是用於管理Servlet生命週期的。 Spring容器,是用於管理Spring Bean生命週期的,如service,dao等。 SpringMVC容器,適用於管理SpringMVC Bean生命週期的,如Controller,ViewResovler等。

Tomcat/Jetty啓動,對於每一個WebApp,依次進行初始化工做:

  1. 對每一個WebApp,都有一個WebApp ClassLoader,和一個ServletContext

  2. ServletContext啓動時,會掃描web.xml配置文件,找到Filter、Listener和Servlet配置

  3. 若是Listener中配有spring的ContextLoaderListener

    • ContextLoaderListener就會收到webapp的各類狀態信息。
    • 在ServletContext初始化時,ContextLoaderListener也就會將Spring IOC容器進行初始化,管理Spring相關的Bean。
    • ContextLoaderListener會將Spring IOC容器存放到ServletContext中
  4. 若是Servlet中配有SpringMVC的DispatcherServlet

    • DispatcherServlet初始化時(其一次請求到達初始化,延遲加載)。
    • 其中,DispatcherServlet會初始化本身的SpringMVC容器,用來管理Spring MVC相關的Bean。
    • SpringMVC容器能夠經過ServletContext獲取Spring容器,並將Spring容器設置爲本身的根容器。而子容器能夠訪問父容器,從而在Controller裏能夠訪問Service對象,可是在Service裏不能夠訪問Controller對象。

附一個描述關係的圖 blog.csdn.net/zhanglf02/a…

純手工打造一個Servlet

基本步驟
  1. 下載並安裝 Tomcat。
  2. 編寫一個繼承 HttpServlet 的 Java 類。
  3. 將 Java 類文件編譯成 Class 文件。
  4. 創建 Web 應用的目錄結構,並配置web.xml。
  5. 部署 Web 應用。
  6. 啓動 Tomcat。
  7. 瀏覽器訪問驗證結果。
  8. 查看 Tomcat 日誌。
目錄介紹
  1. /bin:存放 Windows 或 Linux 平臺上啓動和關閉 Tomcat 的腳本文件。
  2. /conf:存放 Tomcat 的各類全局配置文件,其中最重要的是server.xml。
  3. /lib:存放 Tomcat 以及全部 Web 應用均可以訪問的 JAR 文件。
  4. /logs:存放 Tomcat 執行時產生的日誌文件。
  5. /work:存放 JSP 編譯後產生的 Class 文件。
  6. /webapps:Tomcat 的 Web 應用目錄,默認狀況下把 Web 應用放在這個目錄下。
日誌目錄介紹

這裏簡要介紹各個文件的含義。

  1. catalina.xxx.log主要是記錄 Tomcat 啓動過程的信息,在這個文件能夠看到啓動的 JVM 參數以及操做系統等日誌信息。
  2. catalina.outcatalina.out是 Tomcat 的標準輸出(stdout)和標準錯誤(stderr),這是在 Tomcat 的啓動腳本里指定的,若是沒有修改的話 stdout 和 stderr 會重定向到這裏。因此在這個文件裏能夠看到咱們在MyServlet.java程序裏打印出來的信息:MyServlet 在處理 get 請求…
  3. localhost.xx.log主要記錄 Web 應用在初始化過程當中遇到的未處理的異常,會被 Tomcat 捕獲而輸出這個日誌文件。
  4. localhost_access_log.xx.txt存放訪問 Tomcat 的請求日誌,包括 IP 地址以及請求的路徑、時間、請求協議以及狀態碼等信息。
  5. manager.xxx.log/host-manager.xxx.log存放 Tomcat 自帶的 Manager 項目的日誌信息。
web.xml配置和 @WebServlet註解配置

如下兩種配置均可以將servlet注給servlet容器

<servlet>      
     <servlet-name>myServlet</servlet-name>      
     <servlet-class>MyServlet</servlet-class>   
 </servlet>    
 <servlet-mapping>     
     <servlet-name>myServlet</servlet-name>   
     <url-pattern>/myservlet</url-pattern>   
 </servlet-mapping>
複製代碼
@WebServlet("/myAnnotationServlet")
public class AnnotationServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //TODO
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //TODO

}  
複製代碼
注意

Servlet接口中定義了service方法,沒有doGet/doPost。HttpServlet是一個實現類,實現了service方法,同時留出了doGet/doPost方法讓程序員來實現。

備註

本文是我我的學習了李號雙老師的專欄課程以後,結合專欄文章和老師對同窗答疑整理的學習筆記。僅供分享。更多精彩內容,你們能夠掃描下方二位碼,在極客時間訂閱李號雙老師的《深刻拆解Tomcat & Jetty》。獲取一手學習資料。

相關文章
相關標籤/搜索