Javaweb - 10.3 Servlet 生命周期

目錄

生命周期簡介

生命周期測試

load-on-startup

補充:defaultServlet

Servlet 的繼承結構

1. 頂級的 Servlet 接口

2. 抽線的類 GenericServlet

3. HttpServlet 抽象類

4. 自定義 Servlet

補充:

完!


生命周期簡介

什么是生命周期?

? ? ? ? 應用程序中的對象,不僅在空間上有層次結構的關系,在實踐上也會因為處于運行過程中的不同階段,而表現出不同狀態和不同行為,這就是對象的生命周期

? ? ? ? 簡單的敘述生命周期:就是對象在開始創建,到最后銷毀的過程。

Servlet 容器:

? ? ? ? Servlet 對象是 Servlet 容器創建的,生命周期方法都是由容器(我們目前使用 Tomcat)調用的。這一點和我們之前所編寫的代碼,由很大的不同!在今后的學習中,我們越來越多的對象,都要交給容器或框架來創建,越來越多的方法,都要由容器或框架來調用。

? ? ? ? 我們作為程序員,要盡可能的將經歷放在業務邏輯的實現上!

Servlet 主要的生命周期執行特點:

生命周期測試

還在我們前面的項目工程中,開發一個測試代碼:

package com.zzz.servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/** @author zzr* @date: 2025/07/04  21:24* @description: 測試 servlet 的生命周期*/
@WebServlet("/servletLifeCycle")
public class servletLifeCycle extends HttpServlet {public servletLifeCycle() {System.out.println("構造器");}@Overridepublic void init() throws ServletException {System.out.println("初始化");}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("服務");}@Overridepublic void destroy() {System.out.println("銷毀");}
}

在四處打印的地方打上斷點:

debug 模式運行

為瀏覽器配置好 url 后,回車,發現代碼卡在了“構造器”的斷點處

一步一步向后運行代碼

此時并沒有銷毀。并且,當我們在瀏覽器,刷新重新打開的時候,就只會再打印“服務”了~

停止項目后,會打印“銷毀”

結論:

? ? ? ? 通過生命周期的測試,我們發現:Servlet 對象在容器中是單例的。但,容器又是需要并發的,處理用戶請求的,每個請求在容器中,都會開啟一個線程。

? ? ? ? 多個線程可能會使用相同的 Servlet 對象,但 Servlet 對象在容器中是單例的,所以 Servlety 的成員變量,在多個線程之中也是共享的 ==》 非常非常不建議,在 service 中修改成員變量,在并發請求的時候,會引發線程安全問題~

load-on-startup

我們在前面的 @WebServlet 提到過這個成員變量~

其值是一個數字,含義是:tomcat 在啟動時,實例化該 servlet 的順序。(如果順序號沖突了,tomcat 會自動協調啟動順序~)

    <servlet><servlet-name>servletLifeCycle</servlet-name><servlet-class>com.zzz.servlet.servletLifeCycle</servlet-class>
<!--默認值是 -1 含義是 tomcat 啟動時不會實例化該 servlet其他正整數,例如 15,含義是 在 tomcat啟動時,實例化該 servlet 的順序
--><load-on-startup>15</load-on-startup></servlet><servlet-mapping><servlet-name>servletLifeCycle</servlet-name><url-pattern>/servletLifeCycle</url-pattern></servlet-mapping>

將 servletLifeCycle 中的 @WebServlet 注釋刪掉,取消所有斷點,直接運行程序:

發現自動就為我們準備好了構造器和初始化~

當然也可以在 @WebServlet 中設置 loadOnStartup 的值

注意:我們可以在 tomcat 文件夾下的 conf/web.xml 進行查找,發現有些序號已經占用了,1 - 5 號都已經被占用,我們如果要使用,最好不要重復 1 - 5?號~(這個序號就算不連貫也是可以的,tomcat 會自己匹配~)

補充:defaultServlet

defaulyServlet 是用于加載靜態資源的 servlet,默認隨服務器啟動,默認啟動序號為 1

Servlet 的繼承結構

1. 頂級的 Servlet 接口

源碼如下:

public interface Servlet {void init(ServletConfig var1) throws ServletException;ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;String getServletInfo();void destroy();
}

Servlet 規范接口,所有的 servlet 必須實現

? ? ? ? init:

? ? ? ? ? ? ? ? 初始化方法,容器在構造 servlet 對象后,自動調用的方法,容器負責實例化一個 ServletConfig 對象,并在調用該方法的時候傳入。

? ? ? ? ? ? ? ? ServletConfig 對象可以為 servlet 對象提供初始化參數

? ? ? ? getServletConfig:

? ? ? ? ? ? ? ? 獲取 ServletConfig 對象的方法,后續可以通過該對象獲取 servlet 初始化參數

? ? ? ? service:

? ? ? ? ? ? ? ? 處理請求并做出響應的服務方法,每次請求產生的時候,都是由容器調用。

? ? ? ? ? ? ? ? 容器創建一個 ServletRequest 對象喝 ServletResponse 對象,容器在調用 service 方法時候,傳入這兩個對象。

? ? ? ? getservletInfo:

? ? ? ? ? ? ? ? 獲取 servletInfo 信息的方法

? ? ? ? destory:

? ? ? ? ? ? ? ? servlet 實例在銷毀之前調用的方法,用用作資源釋放

2. 抽線的類 GenericServlet

源碼如下:

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {private static final long serialVersionUID = 1L;private transient ServletConfig config;public GenericServlet() {}public void destroy() {}public String getInitParameter(String name) {return this.getServletConfig().getInitParameter(name);}public Enumeration<String> getInitParameterNames() {return this.getServletConfig().getInitParameterNames();}public ServletConfig getServletConfig() {return this.config;}public ServletContext getServletContext() {return this.getServletConfig().getServletContext();}public String getServletInfo() {return "";}public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}public void init() throws ServletException {}public void log(String message) {ServletContext var10000 = this.getServletContext();String var10001 = this.getServletName();var10000.log(var10001 + ": " + message);}public void log(String message, Throwable t) {this.getServletContext().log(this.getServletName() + ": " + message, t);}public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;public String getServletName() {return this.config.getServletName();}
}

?GenericServlet 抽象類,是對 Servlet 接口一些固定功能的粗糙實現,以及對 service 方法的再次抽象聲明,并定義了一些其他相關功能方法。

private transit ServletConfig config:

? ? ? ? 初始化配置對象作為屬性(transit 是一個特殊的關鍵字。當對象被序列化時,被 transit 修飾的變量不會被序列化,也就是不會被持久化存儲或通過網絡傳輸)

public GenericServle:

? ? ? ? 構造器,為了滿足繼承而準備

public void destory:

? ? ? ? 將 Servlet 中的抽象方法,重寫為普通方法,在方法內部中沒有任何實現的代碼,稱為 destory 的平庸實現 ==》?讓子類可根據需要選擇是否重寫,實現銷毀相關邏輯

public void init() {

? ? ? ? this.config() = config;

? ? ? ? this.init();

}

? ? ? ? tomcat 在調用 init 方法時,會讀取配置信息進入一個 ServletConfig 對象,并將該對象傳入 init 方法。此方法將 config 對象存儲為當前的屬性,并且調用了重載的無參的 init 方法

public void inti:

? ? ? ? 重載的初始化方法,即我們重寫初始化方法對應的方法。

public ServletConfig getServletConfig:

? ? ? ? 返回 ServletConfig 的方法

public abstract void service:

? ? ? ? 再次抽象聲明 service 方法

3. HttpServlet 抽象類

在這個抽象里,側重于 service 方法的處理

源代碼較長,此處選部分重要的進行理解:

    private static final String METHOD_DELETE = "DELETE";private static final String METHOD_HEAD = "HEAD";private static final String METHOD_GET = "GET";private static final String METHOD_OPTIONS = "OPTIONS";private static final String METHOD_POST = "POST";private static final String METHOD_PUT = "PUT";private static final String METHOD_TRACE = "TRACE";

上述屬性,用于定義常見請求方式名的常量值

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest)req;response = (HttpServletResponse)res;} catch (ClassCastException var6) {throw new ServletException(lStrings.getString("http.non_http"));}this.service(request, response);}

request = (HttpServletRequest)req 和 response = (HttpServletResponse)res 都是參數的父轉子操作(子類的方法屬性更多一些~) 再調用重載的 service 方法

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();if (method.equals("GET")) {this.doGet(req, resp);} else if (method.equals("HEAD")) {this.doHead(req, resp);} else if (method.equals("POST")) {this.doPost(req, resp);} else if (method.equals("PUT")) {this.doPut(req, resp);} else if (method.equals("DELETE")) {this.doDelete(req, resp);} else if (method.equals("OPTIONS")) {this.doOptions(req, resp);} else if (method.equals("TRACE")) {this.doTrace(req, resp);} else {resp.sendError(501, errMsg);}}

在 protected 修飾的 service 方法中,先是獲取了請求的方式,然后根據請求方式,調用對應的 do*** 方法

do*** 方法大同小異,這里以 doGet 為例:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = lStrings.getString("http.method_get_not_supported");this.sendMethodNotAllowed(req, resp, msg);}

先獲取對應的字符串,然后調調用 sendMethodNotAllowed 方法,即 sendError 方法,故意響應 405 請求方式不允許的信息。

4. 自定義 Servlet

public class servlet1 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("servlet1 執行了");}
}

在自定義的 Servlet 中,實現接收用戶請求信息,然后做出資源響應

補充:

如果我們自定義的 servlet 中,沒有重寫 service 方法,就會運行父類的 HttpServlet 中的 service 方法,在父類的 service 方法中,就會執行默認的 doGet 和 doPost 方法 ==》 響應 405

我們也可以自定義的 service 方法中,不重寫 service 方法,直接重寫 doGet 和 doPost 方法~

有些從程序員,推薦在自定義的 servlet 中重寫 do*** 方法處理請求,理由:父類中的 service 方法中可能做了一些處理,如果我們直接重寫 service 方法,父類中的 service 方法中的一些處理可能會失效。

但是,目前觀察,直接重寫 service 并不會有什么問題~

后續使用 SpringMVC 框架之后,我們則無需繼承 HttpServlet,處理請求的方法也無需是 do*** 和 service 了

補充:在此處,我們自定義的 servlet 中,要么重寫 service 方法,要么重寫 do*** 方法~

如果同時重寫了 service 和 do*** 方法,service 優先

完!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87732.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87732.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87732.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RSA數字簽名方案的C語言實現(帶測試)

RSA 算法的 C語言實現通常比較復雜&#xff0c;但已經有許多密碼算法庫實現了 RSA 算法&#xff0c;例如OpenSSL、Libgcrypt? 和 Botan ?等。我們可以在這些庫的基礎上進行配置或移植&#xff0c;從而快速實現密碼算法。但這些庫主要面向大量設備進行優化&#xff0c;如通用計…

創客匠人視角:知識變現與創始人 IP 打造的破局之道

當知識付費從流量紅利期進入精耕細作階段&#xff0c;為何專業能力強的內容創作者反而難以變現&#xff1f;創客匠人通過 1500 案例陪跑發現&#xff1a;缺乏 IP 思維的知識輸出如同霧中航行&#xff0c;而創始人 IP 打造正是連接知識價值與商業變現的核心橋梁。一、定位重構&…

結構分析設計軟件 SCIA Engineer 25.0 x64

詳情 Nemetschek SCIA Engineer是一家從事多項目編程、分析和軟件設計的公司。該軟件具有廣泛的不同功能。該軟件可用于以簡單的方式設計建筑物、工業工廠和橋梁。 Nemetschek SCIA Engineer軟件的特點和功能&#xff1a; BIM模型人 使用網格和故事 3D風 自由負載 互聯網…

怎么處理[TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark

這個錯誤說明 Elasticsearch 的磁盤空間嚴重不足&#xff0c;已觸及最高級別&#xff08;flood-stage&#xff09;的水位線。作為自我保護機制&#xff0c;Elasticsearch ?自動將受影響的索引設置為只讀模式 (read-only-allow-delete)?&#xff0c;從而阻止寫入操作&#xff…

pytorch學習-11卷積神經網絡(高級篇)

2.線性模型 3.梯度下降算法 4.反向傳播(用pytorch算梯度) 5.用pytorch實現線性回歸 6.logistic回歸 7.處理多維特征的輸入 8.加載數據集 9.多分類問題 10.卷積神經網絡(基礎篇) 11.卷積神經網絡&#xff08;高級篇&#xff09;_嗶哩嗶哩_bilibili 11.1 GoogleNet Google…

ubuntu 安裝QT

在 Ubuntu 系統上安裝 Qt 可以通過以下步驟完成&#xff0c;以下是詳細的安裝指南 &#xff1a; 1. 安裝前的準備工作 在開始安裝 Qt 之前&#xff0c;需要確保你的 Ubuntu 系統已經更新到最新版本&#xff0c;并且安裝了一些必要的依賴。 1.1 更新系統 首先&#xff0c;打…

CppCon 2018 學習:RAPID PROTOTYPING OF GRAPHICS SHADERS IN

這段內容在講**著色器&#xff08;Shader&#xff09;**的基礎概念&#xff0c;尤其是它在現代 GPU&#xff08;圖形處理單元&#xff09;中的作用。以下是逐條解釋與理解&#xff1a; “Depicting depth perception in 3D models or illustrations by varying levels of darkn…

Angular v20版本正式發布

過去幾年對 Angular 來說很具變革性,我們推出了像 Signals 這樣的反應性功能和 Zoneless 應用的強大能力。我們希望這些功能可以幫助 Angular 社區構建下一代的 Web 應用,實現快速上市和強大的性能。 我們的旅程才剛剛開始!Angular v20 是最新的發布版本,我們花費了無數個小…

Oracle如何使用序列 Oracle序列使用教程

Oracle序列&#xff08;sequence&#xff09;是一種數據庫項&#xff0c;能夠生成一個整數序列。通常用于填充數字類型的主鍵列。 Oracle序列 Oracle序列使用教程&#xff1a; 1、創建序列&#xff1a; CREATE SEQUENCE sequence_name[START WITH start_num][INCREMENT BY incr…

深入探索 Vanna:讓數據庫交互更智能

深入探索 Vanna&#xff1a;讓數據庫交互更智能 在數字化時代&#xff0c;與數據庫進行高效交互是許多開發者、數據分析師和企業面臨的挑戰。傳統的 SQL 查詢編寫不僅需要對數據庫結構有深入的了解&#xff0c;還需要花費大量的時間和精力來調試和優化。Vanna&#xff0c;一個…

C#上位機之網口通信與協議!

文章目錄前言一、網口通信概念二、使用網口通信準備三、使用步驟前言 C#上位機之網口通信與協議&#xff01; 一、網口通信概念 定義 &#xff1a;Socket 可以理解為一個通信端點&#xff0c;它提供了應用程序與網絡之間的接口&#xff0c;使得應用程序能夠在網絡上發送和接收…

Android Studio 創建類時如何自動添加類注釋

打開IDEA或AS&#xff0c;點擊菜單欄File——Settings——Editor——File and Code Templates。 點擊右邊Tab頁的Includes&#xff0c;選擇File Header&#xff0c;修改類頭模版&#xff0c;如圖&#xff1a; 記得選中Project&#xff0c;否則默認是整個AS都會進行設置

C++11:shared_ptr的設計哲學(原理+源碼):內存安全和性能的架構權衡

0.簡介 在C編程世界中&#xff0c;內存管理是一把雙刃劍&#xff0c;手動管理帶來了極致的內存控制能力&#xff0c;但也帶來了像內存泄漏&#xff0c;野指針等問題&#xff1b;自動垃圾回收雖然安全&#xff0c;但卻會帶來一定的性能損耗。本文將介紹C11引入shared_ptr&#…

Mysql EXPLAIN 執行計劃

EXPLAIN SELECT SQl。。。。界面filtered儲引擎返回的數據在經過服務器層 WHERE 條件過濾后&#xff0c;剩余數據占總行數的百分比估計值rows * filtered/100 越接近100%效率越高rowspossible_keys 可能選擇的索引key最終決定選擇的行partitions問了哪些分區select_type查詢…

力扣刷題記錄【1】146.LRU緩存

前言&#xff1a; 請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類&#xff1a; LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存中&#xff0c;則返回關鍵字的值&…

西門子S7-1200 PLC主流通信方法及應用

一、通信基礎 1. 網絡術語與設備 - 關鍵設備&#xff1a;交換機、路由器、網關等。 - 物理接口&#xff1a;RS-485&#xff08;支持多點通信&#xff09;、RS-232C&#xff08;點對點串行通信&#xff09;。 2. OSI參考模型 - 核心框架&#xff1a;理解協議分層&…

MySQL實現任意級子目錄的主要方案以及區別

常見的實現方案及區別 1. 鄰接表&#xff08;Adjacency List&#xff09; 方案描述&#xff1a; 每條記錄存儲一個節點的父節點ID。 表結構大致&#xff1a; id INT PRIMARY KEY, name VARCHAR(...), parent_id INT -- 指向父節點的ID&#xff0c;根節點為NULL或0優點&…

Linux網絡socket套接字(完)(5)

文章目錄前言一、多進程版的Tcp網絡程序捕捉SIGCHLD信號讓孫子進程提供服務二、多線程版的Tcp網絡程序三、線程池版的Tcp網絡程序四、Tcp協議通訊流程通訊流程總覽三次握手的過程數據傳輸的過程四次揮手的過程總結前言 結束嘍&#xff0c;至少這個Tcp套接字有關內容要結束了~ ?…

Web3 Study Log 003

Web3 Study Log 003 2025-7-5 這幾天各種各樣的瑣事&#xff0c;處理完了&#xff0c;真的煩&#xff0c;估計能消停一段時間了… 今天終于能夠坐下來好好學習&#xff0c;今天學習了chainlink的使用&#xff0c;能夠獲取 ETH/USD 實時價格&#xff0c;然后寫了一個簡單的眾…

Kotlin:2.1.20 的新特性

一、概述 The Kotlin 2.1.20 release is here! Here are the main highlights: Kotlin 2.1.20發布了&#xff0c;主要亮點如下&#xff1a; K2 compiler updates: updates to the new kapt and Lombok pluginsKotlin Multiplatform: new DSL to replace Gradle’s Application …