一. servlet
1.1 什麼是servlet?
servlet是一個java的服務端應用程序。類似一個java組件或者小插件,用來處理客戶端和服務端之間的請求和響應。需要依賴servlet容器,由容器來實例化和調用service方法
servlet讓客戶端和服務器端不僅僅是進行簡單的靜態資源傳輸, 它可以實現動態的資源和一些複雜的業務邏輯。
我們使用的spring mvc和後面的springboot,都是基於dispatcherServlet來調用的
1.2 servlet和tomcat處理一個http請求的過程(tomcat7)
- 瀏覽器客戶端先和Tomcat的Connector組件建立連接
- 客戶端向Tomcat發起http請求,Connector組件分析請求信息,封裝成request和response對象(不是HttpServletRequest)
- Connector中的Mapper會根據請求域名和地址匹配到servlet容器,設置到reqeust屬性中
- Connector中的適配器Adapt將Request和response轉換成HttpServletRequest和HttpServletResponse對象,並且根據上面找到的servlet容器,交給容器處理
- servlet容器調用servlet的doGet()或doPost()方法,如果是第一次則先初始化,servlet執行業務邏輯,並把結果寫到response中
- 容器將請求數據封裝成HttpServletRequest和HttpServletResponse對象,調用doGet()或doPost(),servlet執行業務邏輯,並把結果寫到response中
- 返回response給Connector,Connector返回給瀏覽器
二. mvc流程
-
m - model 模型
數據和行爲
-
v - view 視圖
模型的展示,也就是頁面
-
c - controller 控制器
接受請求,將數據結果返回給視圖,展示視圖
SpringMvc主要是圍繞着DispatcherServlet進行:
- 用戶發起的請求經過web服務器到dispatcherServlet
- dispatcherServlet調用HandlerMapping,根據請求的url找到找到對應的處理器調用鏈,包括處理器Handler和攔截器,返回給dispatcherServlet
- dispatcherServlet再根據Handler選擇合適的適配器HandlerAdapt(處理器適配器)來處理,其實就是調用Controller的方法,返回modelAndView
- dispatcherServlet再用視圖解析器ViewResolve去解析ModelAndView,返回視圖View
- DispatcherServlet拿到視圖,將模型數據渲染填充到View中
- 返回View給瀏覽器
三. tomcat
3.1 什麼是tomcat
tomcat是阿帕奇的一個Web 應用服務器.也是一個servlet容器.
- web服務器,簡單說就是可以讓其他的客戶端在網上能訪問到服務器靜態資源的一個設備,比如瀏覽圖片,靜態網頁,下載文件等。比如阿帕奇的nginx
- 而web應用服務器,是針對某個應用或者業務邏輯而實現的,通過組件可以完成一些業務邏輯比如操作數據庫,處理請求返回動態的資源
四. NIO
4.1 NIO和普通IO
NIO又叫做非阻塞io,它與傳統的io的區別是:
IO | NIO |
---|---|
面向流 | 面向緩衝buffer |
阻塞IO | 非阻塞IO |
傳統IO,當一個線程處理一個讀寫IO操作的時候,該線程會一直被阻塞,知道流的傳輸完畢。此間線程不能做其他事,浪費資源。
而在NIO的非阻塞模式下,線程發送數據與接收數據都是通過“通道”進行的,線程只需要去詢問通道是否有數據需要處理,有則處理,無則立即返回不會進行等待。
所以NIO的單線程可以處理多個通道的IO操作。
4.2 NIO的概念
a. Buffer
Buffer通常是一個數組,表示一個緩衝區。NIO的讀寫操作都是操作緩存。比如寫,是先將數據寫入Buffer,然後再寫到通道Channel的
b. Channel
通道,和流不同,通道是雙向的,流是單向的。流只能是讀或者寫,通道可以讀也可以寫。
C. Selector
選擇器。通道會註冊到選擇器上,並指定監聽的事件類型,比如ACCET,READ,WRITE。
只要開啓一個線程不斷輪詢註冊在選擇器上的通道,選擇器會調用select()方法,這個方法是阻塞的,如果監聽到註冊的通道的感興趣的事件,會調用相應的方法處理
4.3 tomcat中的NIO
可以參考前面博文:
Tomcat 接收連接的accept流程
簡單的說,就是tomcat內部分爲兩大塊:
Connector和Container容器
Connector中又分爲:
- Http11NioProtocol
- NioEndpoint
- Acceptor
- Poller
- Worker
- Http11ConnectionHandler
- NioEndpoint
- Mapper
- CoyoteAdapter
Acceptor
Acceptor線程組,作爲生產者的角色
- 通過阻塞的accept()方法,建立與客戶端的連接,並獲取到SocketChannel對象
- 將SocketChannel對象封裝成NioChannel對象
- 再將NioChannel對象封裝到PollerEvent對象中,放到Poller的隊列中
Poller
Poller線程組,作爲消費者的角色,是個典型的生產者-消費者模式,Acceptor與Poller線程之間通過queue通信
- 從Poller隊列中取出PollerEvent消費
- 將PollerEvent註冊到Selector中
- Poller線程的run方法是一個死循環,其中Selector進行select()操作,如果註冊的Channel中有可讀的操作,丟到Worker線程池中開啓一個線程處理
Worker
到這一步就是開始解析請求數據了
- 解析請求數據創建一個臨時的Request對象(不是HttpServletRequest,org.apache.coyote.Request),交給CoyoteAdapter處理
- CoyoteAdapter會將Request對象,轉成org.apache.catalina.connector.Request對象。
- 再調用Mapper,根據請求的Url,分析出對應的Host,Context,以及對應的Servlet的封裝wrapper,並將這些參數都封裝到Request中
- 接着就將Request交給Container容器處理,也就是Servlet容器
- 容器根據Request屬性中的映射關係,找到對應的Servlet處理
- Servlet調用doGet(),doPost()方法,返回Response對象
五. http
5.1 什麼是http
http是一種規定好的客戶端和服務端傳輸信息的一種協議.
它要求傳輸的數據分爲三個部分: 信息行,信息頭,信息體.
比如請求:
- 請求行
- 請求頭
- 請求體
5.3 錯誤碼
在返回的數據中,響應行中攜帶狀態碼和狀態描述.常見的狀態碼:
2xx是請求正常,3xx是重定向,4xx是請求錯誤,5xx是服務器內部錯誤
狀態碼 | 含義 |
---|---|
200 | 請求成功 |
301 | 永久重定向 |
302 | 臨時重定向 |
400 | 請求的參數語法錯誤 |
404 | 資源找不到 |
405 | 請求的方法與後臺定義的不一致 |
500 | 服務器內部的錯誤 |