---
# System prepended metadata

title: Servlet的生命週期
tags: [Java Web-Servlet]

---

# Servlet的生命週期
###### tags: `Java Web-Servlet`

### 1.生命週期：從出生到死亡的過程就生命週期。對應servlet的三種方法：init()、service()、destroy()
### 2.默認情況下：
第一次接收請求時，這個servlet會進行實例化(調用構造方法)、初始化(調用init(())，然後服務(調用servlet())
#### servlet初始化、運行
![](https://i.imgur.com/d0ikLrf.png)
#### servlet銷毀(終止)
![](https://i.imgur.com/EOjYZx7.png)
從第二次請求開始時，每一次都是服務
![](https://i.imgur.com/h0YRBs0.png)
當容器關閉時，其中的所有的servlet實例會被銷毀，調用銷毀方法
### 3.通過案例我們發現:Servlet實例tomcat只會創建一個，所有的請求都是這個實例去響應。
默認情況下，第一次請求時，tomcat才會去實例化、初始化，然後再服務
![](https://i.imgur.com/lFqcyXb.png)
這樣的好處是什麼？提高系統的啟動速度
這樣的缺點是什麼？第一次請求時耗時較長
因此得出結論：如果需要提高系統的啟動速度，當前默認情況就是這樣
如果需要提高響應速度，我們應該要設置servlet的響應時機
### 4.Servlet的初始化時機：
我們可以通過<load-on-startup>設置servlet啟動的先後順序，數字越小，啟動越靠前，最小值為0
### 5.servlet在容器中：是單例的(不管幾個客戶端來訪問，都使用同一個實例來響應)、線程不安全的
#### 單例：不管幾個客戶端來訪問，所有的請求都是同一個實例去響應
#### 線程不安全：一個線程需要根據這個實例中的某個成員變量值去做邏輯判斷。
![](https://i.imgur.com/Qa8RHOO.png)    
但是中間某個時機，另一個線程改變了這個成員變量的值，從而導致第一個線程的執行路徑發生了變化
我們已經知道了Servlet是線程不安全的，給我們的啟發：盡量不要在servlet中定義成員變量。
如果不得不定義成員變量，那麼不要去：
#### (1)不要去修改成員變量的值
#### (2)不要根據成員變量的值，去做成員判斷
    
#### 500：服務器內部錯誤   
    因為構造子改成private，導致無法例化
```java=
    private Demo02Servlet(){
        System.out.println("正在實例化");
    }
```    
![](https://i.imgur.com/98Dbvkt.png)    