Servlet/Tomcat/ Spring 之間的關系


0.基礎知識

在idea中打開servlet的源碼:

 

 

可以看見servlet就是一個接口;接口就是規定了一些規范,使得一些具有某些共性的類都能實現這個接口,從而都遵循某些規范。

有的人往往以為就是servlet直接處理客戶端的http請求,其實並不是這樣,servlet並不會去監聽8080端口;直接與客戶端打交道是“容器”,比如常用的tomcat。

客戶端的請求直接打到tomcat,它監聽端口,請求過來后,根據url等信息,確定要將請求交給哪個servlet去處理,然后調用那個servlet的service方法,service方法返回一個response對象,tomcat再把這個response返回給客戶端。

 

 

1. Servlet的生命周期

 

從創建到毀滅:

 

  1. 調用 init() 方法初始化
  2. 調用 service() 方法來處理客戶端的請求
  3. 調用 destroy() 方法釋放資源,標記自身為可回收
  4. 被垃圾回收器回收

 

由上面可以看見,servlet的init方法和destroy方法,一般容器調用這兩個方法之間的過程,就叫做servlet的生命周期。

調用的整個過程就如上圖所示。

當請求來容器第一次調用某個servlet時,需要先初始化init(),

但當某個請求再次打到給servlet時,容器會起多個線程同時訪問一個servlet的service()方法。

 

 

由此可以看出,多個客戶訪問同一service()方法,會涉及線程安全的問題。

 

如果service()方法沒有訪問Servlet的成員變量也沒有訪問全局的資源比如靜態變量、文件、數據庫連接等,而是只使用了當前線程自己的資源,比如非指向全局資源的臨時變量、request和response對象等。該方法本身就是線程安全的,不必進行任何的同步控制。

如果service()方法訪問了Servlet的成員變量,但是對該變量的操作是只讀操作,該方法本身就是線程安全的,不必進行任何的同步控制。

如果service()方法訪問了Servlet的成員變量,並且對該變量的操作既有讀又有寫,通常需要加上同步控制語句。

如果service()方法訪問了全局的靜態變量,如果同一時刻系統中也可能有其它線程訪問該靜態變量,如果既有讀也有寫的操作,通常需要加上同步控制語句。

如果service()方法訪問了全局的資源,比如文件、數據庫連接等,通常需要加上同步控制語句。

 

 

面試問題:Servlet如何同時處理多個請求訪問? 

單實例多線程: 主要是請求來時,會由線程調度者從線程池李取出來一個線程,來作為響應線程。這個線程可能是已經實例化的,也可能是新創建的。


Servlet容器默認是采用單實例多線程的方式處理多個請求的: 
1.當web服務器啟動的時候(或客戶端發送請求到服務器時),Servlet就被加載並實例化(只存在一個Servlet實例); 
2.容器初始化化Servlet主要就是讀取配置文件(例如tomcat,可以通過servlet.xml的設置線程池中線程數目,初始化線程池通過web.xml,初始化每個參數值等等。 
3.當請求到達時,Servlet容器通過調度線程(Dispatchaer Thread) 調度它管理下線程池中等待執行的線程(Worker Thread)給請求者; 
4.線程執行Servlet的service方法; 
5.請求結束,放回線程池,等待被調用; 
(注意:避免使用實例變量(成員變量),因為如果存在成員變量,可能發生多線程同時訪問該資源時,都來操作它,照成數據的不一致,因此產生線程安全問題)

 

從上面可以看出: 
第一:Servlet單實例,減少了產生servlet的開銷; 
第二:通過線程池來響應多個請求,提高了請求的響應時間; 
第三:Servlet容器並不關心到達的Servlet請求訪問的是否是同一個Servlet還是另一個Servlet,直接分配給它一個新的線程;如果是同一個Servlet的多個請求,那么Servlet的service方法將在多線程中並發的執行; 
第四:每一個請求由ServletRequest對象來接受請求,由ServletResponse對象來響應該請求;

 

 

 

 

 2. Spring 

 

 任何Spring Web的entry point,都是servlet。

 

大名頂頂的spring框架已經風靡多時,一個事物的出現和流行都是會有原因的,那么為什么spring 框架會出現呢?原因就是為了簡化java開發

spring的核心就是通過依賴注入、面向切面編程aop、和模版技術,解耦業務與系統服務,消除重復代碼。借助aop,可以將遍布應用的關注點(如事物和安全)從它們的應用對象中解耦出來。

 

 

 Spring 中的Bean

 1) POJO和JavaBean的區別 : 

"Plain Ordinary Java Object",簡單普通的java對象。主要用來指代那些沒有遵循特定的java對象模型,約定或者框架的對象。

POJO的內在含義是指那些:
有一些private的參數作為對象的屬性,然后針對每一個參數定義get和set方法訪問的接口。
沒有從任何類繼承、也沒有實現任何接口,更沒有被其它框架侵入的java對象。

JavaBean 是一種JAVA語言寫成的可重用組件。JavaBean符合一定規范編寫的Java類,不是一種技術,而是一種規范。大家針對這種規范,總結了很多開發技巧、工具函數。符合這種規范的類,可以被其它的程序員或者框架使用。它的方法命名,構造及行為必須符合特定的約定:

  1. 所有屬性為private。

  2. 這個類必須有一個公共的缺省構造函數。即是提供無參數的構造器。

  3. 這個類的屬性使用getter和setter來訪問,其他方法遵從標准命名規范。

  4. 這個類應是可序列化的。實現serializable接口。

因為這些要求主要是靠約定而不是靠實現接口,所以許多開發者把JavaBean看作遵從特定命名約定的POJO。

 

spring中,應用對西那個生存於spring容器中,spring 容器創建對象,裝配它們,管理它們的整個生命周期。spring容器通過依賴注入,管理構成應用的組件,它會創建相互協作的組件之間的關聯。

2) Bean的生命周期

 

 

 Spring MVC

 

 

 

 

 Spring MVC的運行流程:

 

 

 

 

 

 

 

 

 

 

 

 

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM