Servlet及相關類和介面

来源:https://www.cnblogs.com/Y-oung/archive/2018/02/05/8419644.html
-Advertisement-
Play Games

上一篇介紹了在Web項目中web.xml文件的配置信息,本篇主要介紹裡面非常重要的配置——Servlet配置,重點介紹與Servlet相關的幾個介面和類,包括Servlet介面、ServletConfig介面、ServletContext介面、GenericServlet類、HttpServlet類 ...


        上一篇介紹了在Web項目中web.xml文件的配置信息,本篇主要介紹裡面非常重要的配置——Servlet配置,重點介紹與Servlet相關的幾個介面和類,包括Servlet介面、ServletConfig介面、ServletContext介面、GenericServlet類、HttpServlet類。

        1、Servlet介紹

        什麼是Servlet:

        百度的解釋是“小服務程式或服務連接器,用Java編寫的伺服器端程式,主要功能在於互動式地瀏覽和修改數據,生成動態Web內容”。Servlet是Java語言裡面的一個介面,任何直接或間接實現了Servlet介面的類都可稱為Servlet類。

        Servlet與Tomcat的關係:

        Tomcat 是Web應用伺服器,是Servlet的容器。Tomcat 作為Servlet容器,在啟動時可以創建Servlet類的實例,調用init()方法對Servlet進行初始化,同時負責處理客戶請求,把請求傳送給Servlet,並將Servlet的響應傳送回給客戶。可以說,Servlet是一種運行在支持Java語言的伺服器上的組件。在web.xml文件中,通過<servlet>標簽配置Servlet類的相關信息,詳細配置請見 http://www.cnblogs.com/Y-oung/p/8401549.html 。

        2、Servlet介面

        先看源碼:

package javax.servlet;

import java.io.IOException;

public abstract interface Servlet {
    public abstract void init(ServletConfig paramServletConfig)
            throws ServletException;

    public abstract ServletConfig getServletConfig();

    public abstract void service(ServletRequest paramServletRequest,
            ServletResponse paramServletResponse) throws ServletException,
            IOException;

    public abstract String getServletInfo();

    public abstract void destroy();
}

        init():初始化方法,在Tomcat對Servlet實例化後,Servlet容器會調用init()方法來初始化該對象,讓Servlet對象在處理客戶請求前可以完成一些初始化工作,例如:建立資料庫的連接,獲取配置信息等。在Servlet的整個生命周期中,init()方法自始至終只會被調用一次。init()方法有一個類型為ServletConfig的參數,Servlet容器通過這個參數向Servlet傳遞配置信息。Servlet使用ServletConfig對象從web.xml文件中獲取以名-值對形式提供的初始化參數。另外,在Servlet中,還可以通過ServletConfig對象獲取描述Servlet運行環境的ServletContext對象,使用該對象,Servlet可以和它的Servlet容器進行通信。

如圖中紅圈裡面的配置信息可以在MainServlet類的init()方法裡面解析。

        getServletConfig():該方法返回容器調用init()方法時傳遞給Servlet對象的ServletConfig對象,ServletConfig對象包含了Servlet的初始化參數(如上圖紅圈裡的配置信息)。關於ServletConfig介面下麵會介紹。

        service():該方法是用來處理客戶端請求(在service()方法被容器調用之前,必須確保init()方法正確完成)的核心方法。容器會構造一個表示客戶端請求信息的請求對象(類型為ServletRequest)和一個用於對客戶端進行響應的響應對象(類型為ServletResponse)作為參數傳遞給service()。在service()方法中,Servlet對象通過ServletRequest對象得到客戶端的相關信息和請求信息,在對請求進行處理後,調用ServletResponse對象的方法設置響應信息。

        getServletInfo():該方法返回一個包括了關於Servlet的信息的字元串(如作者、版本和版權等信息),返回的應該是純文本字元串,而不是任何類型的標記。

        destroy():該方法用來銷毀Servlet對象。當容器檢測到一個Servlet對象應該從服務中被移除的時候,容器會調用該對象的destroy()方法,以便讓Servlet對象可以釋放它所使用的資源,該方法同樣只會執行一次。當需要釋放記憶體或者容器關閉時,容器就會調用Servlet對象的destroy()方法,在Servlet容器調用destroy()方法前,如果還有其他的線程正在service()方法中執行容器會等待這些線程執行完畢或者等待伺服器設定的超時值到達。一旦Servlet對象的destroy()方法被調用,容器不回再把請求發送給該對象。如果需要改Servlet再次為客戶端服務,容器將會重新產生一個Servlet對象來處理客戶端的請求。在destroy()方法調用之後,容器會釋放這個Servlet對象,在隨後的時間內,該對象會被java的垃圾收集器所回收。

        可以看到,Servlet介面裡面只有五個方法:init()、getServletConfig()、service()、getServletInfo()、destroy()。其中init()、service()、destroy()三個方法是和servlet生命周期相關的方法,在生命周期的不同時間段內會執行不同的方法,其順序是init()->service()->destroy()。其中init()、destroy()方法在servlet生命周期中都只執行一次,而service()方法可以多次執行。Servlet介面是Servlet類最底層、最基礎、最重要的介面。

        3、ServletConfig介面

        先看源碼:

package javax.servlet;

import java.util.Enumeration;

public abstract interface ServletConfig {
    public abstract String getServletName();

    public abstract ServletContext getServletContext();

    public abstract String getInitParameter(String paramString);

    public abstract Enumeration<String> getInitParameterNames();
}

        getServletName():獲取web.xml文件裡面的servlet的名字(即<servlet-name>標簽配置的名字)。

        getServletContext():獲取ServletContext對象,下麵會介紹ServletContext介面。

        getInitParameter():獲取web.xml文件在servlet標簽中配置的參數值(註意是servlet標簽,而不是其他標簽配置的參數值)。

        getInitParameterNames():獲取在Servlet中所有初始化參數的名字,也就是key值,可以通過key值,來找到各個初始化參數的value值(註意返回的是枚舉類型)。

       

 

 

 

 

 

 

 

 

可以看到,ServletConfig介面裡面的方法主要是獲取web.xml文件里和servlet相關的配置信息。

        4、ServletContext介面

        先看源碼:

package javax.servlet;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Map;
import java.util.Set;
import javax.servlet.descriptor.JspConfigDescriptor;

public abstract interface ServletContext {
    public static final String TEMPDIR = "javax.servlet.context.tempdir";
    public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";

    public abstract ServletContext getContext(String paramString);

    public abstract String getContextPath();

    public abstract int getMajorVersion();

    public abstract int getMinorVersion();

    public abstract int getEffectiveMajorVersion();

    public abstract int getEffectiveMinorVersion();

    public abstract String getMimeType(String paramString);

    public abstract Set<String> getResourcePaths(String paramString);

    public abstract URL getResource(String paramString)
            throws MalformedURLException;

    public abstract InputStream getResourceAsStream(String paramString);

    public abstract RequestDispatcher getRequestDispatcher(String paramString);

    public abstract RequestDispatcher getNamedDispatcher(String paramString);

    public abstract Servlet getServlet(String paramString)
            throws ServletException;

    public abstract Enumeration<Servlet> getServlets();

    public abstract Enumeration<String> getServletNames();

    public abstract void log(String paramString);

    public abstract void log(Exception paramException, String paramString);

    public abstract void log(String paramString, Throwable paramThrowable);

    public abstract String getRealPath(String paramString);

    public abstract String getServerInfo();

    public abstract String getInitParameter(String paramString);

    public abstract Enumeration<String> getInitParameterNames();

    public abstract boolean setInitParameter(String paramString1,
            String paramString2);

    public abstract Object getAttribute(String paramString);

    public abstract Enumeration<String> getAttributeNames();

    public abstract void setAttribute(String paramString, Object paramObject);

    public abstract void removeAttribute(String paramString);

    public abstract String getServletContextName();

    public abstract ServletRegistration.Dynamic addServlet(String paramString1,
            String paramString2);

    public abstract ServletRegistration.Dynamic addServlet(String paramString,
            Servlet paramServlet);

    public abstract ServletRegistration.Dynamic addServlet(String paramString,
            Class<? extends Servlet> paramClass);

    public abstract <T extends Servlet> T createServlet(Class<T> paramClass)
            throws ServletException;

    public abstract ServletRegistration getServletRegistration(
            String paramString);

    public abstract Map<String, ? extends ServletRegistration> getServletRegistrations();

    public abstract FilterRegistration.Dynamic addFilter(String paramString1,
            String paramString2);

    public abstract FilterRegistration.Dynamic addFilter(String paramString,
            Filter paramFilter);

    public abstract FilterRegistration.Dynamic addFilter(String paramString,
            Class<? extends Filter> paramClass);

    public abstract <T extends Filter> T createFilter(Class<T> paramClass)
            throws ServletException;

    public abstract FilterRegistration getFilterRegistration(String paramString);

    public abstract Map<String, ? extends FilterRegistration> getFilterRegistrations();

    public abstract SessionCookieConfig getSessionCookieConfig();

    public abstract void setSessionTrackingModes(
            Set<SessionTrackingMode> paramSet) throws IllegalStateException,
            IllegalArgumentException;

    public abstract Set<SessionTrackingMode> getDefaultSessionTrackingModes();

    public abstract Set<SessionTrackingMode> getEffectiveSessionTrackingModes();

    public abstract void addListener(String paramString);

    public abstract <T extends EventListener> void addListener(T paramT);

    public abstract void addListener(Class<? extends EventListener> paramClass);

    public abstract <T extends EventListener> T createListener(
            Class<T> paramClass) throws ServletException;

    public abstract void declareRoles(String[] paramArrayOfString);

    public abstract ClassLoader getClassLoader();

    public abstract JspConfigDescriptor getJspConfigDescriptor();
}

        Tomcat為每個web項目都創建一個ServletContext實例,在Tomcat啟動時創建,伺服器關閉時銷毀,在一個web項目中共用數據,管理web項目資源,為整個web配置公共信息等。每一個web項目都存在一個ServletContext實例,每個Servlet都可以訪問它。可以看到,ServletContext介面裡面的方法很多,下麵根據功能介紹其中的方法。

        在Web應用範圍記憶體取共用數據的方法:

        setAttribute(String paramString, Object paramObject):把一個Java對象與一個屬性名綁定,並把它存入到ServletContext中。paramString參數指定屬性名,paramObject參數標識共用的數據。
        getAttribute(String name):根據參數給定的屬性名,返回一個Object類型的對象,它表示ServletContext中與屬性名匹配的屬性值。
        getAttributeNames():返回一個Enumeration對象,該對象包含了所有存放在ServletContext中的屬性名。
        removeAttribute(String name):根據參數指定的屬性名,從ServletContext中刪除匹配的屬性。

        訪問當前Web應用的資源:
        getContextPath():返回當前Web應用的URL入口。
        getInitParameter(String name):根據給定的參數名,返回Web應用範圍內初始化參數值。在web.xml文件中,直接在<web-app>跟元素下定義的<context-param>元素表示應用範圍內的初始化參數。
        getInitParameterNames():返回一個Enumeration對象,它包含了Web應用範圍內的所有初始化參數。
        getServletContextName():返回Web應用的名字,即web.xml文件中<display-name>元素的值。
        getRequestDispatcher(String path):返回一個用於向其他Web組件轉發請求的RequestDispatcher對象。

        訪問Servlet容器中的其他Web應用:
        getContext(String uripath):根據參數指定的URI,返回當前Servlet容器中其他Web應用的ServletContext對象。
        訪問Servlet容器的相關信息:
        getMajorVersion():返回Servlet容器支持的Java Servlet API的主版本號。
        getMinorVersion();返回Servlet容器支持的Java Servlet API的次版本號。
        getServletInfo():返回Servlet容器的名字和版本。

        訪問伺服器端的文件系統資源:
        getRealPath(String path):根據參數指定的虛擬路徑,返迴文件系統中的一個真實路徑。
        getResource(String path):返回一個映射到參數指定的路徑的URL。
        getResourceAsStream(String path):返回一個用於讀取參數指定的文件的輸入流。
        getMimeType(String file):返回參數指定的文件的MIME類型。

        輸出日誌:
        log(String msg)向Servlet的日誌文件中寫日誌。
        log(String message , java.lang.Throwable throwable):向Servlet的日誌中寫錯誤日誌,以及異常的堆棧信息。

        5、GenericServlet類

         先看源碼:

package javax.servlet;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;

public abstract class GenericServlet implements Servlet, ServletConfig,
        Serializable {
    private static final long serialVersionUID = 1L;
    private transient ServletConfig config;

    public void destroy() {
    }

    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }

    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }

    public String getServletInfo() {
        return "";
    }

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        init();
    }

    public void init() throws ServletException {
    }

    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }

    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }

    public abstract void service(ServletRequest paramServletRequest,
            ServletResponse paramServletResponse) throws ServletException,
            IOException;

    public String getServletName() {
        return this.config.getServletName();
    }
}

        可以看到,GenericServlet類是一個抽象的(abstract)類,所以它無法被實例化。它繼承了三個介面,其中Servlet和ServletConfig介面是前面介紹過的,可以看出GenericServlet類裡面大多數方法都是這兩個介面裡面的方法,所以這個類其實是整合了這兩個介面,給出了設計servlet的一些骨架,定義了servlet生命周期,還有一些得到名字、配置、初始化參數的方法,使得編寫servlet類時更方便。GenericServlet類裡面所有繼承了這兩個介面的方法的功能,在本文前面已經詳細介紹,這裡只說明一下這個類裡面新增的方法:log(String msg)、log(String message, Throwable t)、init()。

        兩個log()方法:通過ServletContext對象將Servlet的類名和給定的信息寫入log文件中。

        兩個init()方法:init(ServletConfig config)方法是實現了Servlet介面中的方法,作用是可以通過getServletConfig()方法獲取ServletConfig對象。如果你覆蓋了這個方法,你必須調用super.init(config),這樣GenericServlet類的其他方法才能正常工作。而它下麵還調用了無參的init()方法,也就是GenericServlet類自定義的無參方法。為什麼還要定義這個無參數的init()方法呢?其實這個無參數的init()方法是專門留給開發者使用的,開發者只需要覆蓋這個方法就可以很方便的在方法裡面擴充一些功能,比如對自己寫的Servlet類初始化時可以在這個方法裡面進行,解析web.xml文件裡面關於servlet配置的信息時可以在這個方法裡面。這樣就不需要覆蓋init(ServletConfig config)方法了,不需要存儲config對象,也不需要調用super.init(config)。

        儘管GenericServlet類實現了Servlet和ServletConfig介面的功能,但它的service方法中的參數還是ServletRequest,ServletResponse,它處理的還只一般的Servlet請求,並沒有跟http相關對象掛鉤。service方法是和應用層協議無關的,也就是說你有可能用非http協議實現它。而我們平時通過瀏覽器訪問網站時,基本上都是HTTP請求(當然還有FTP請求),請求方式包括GET、POST等,顯然如果直接使用service方法會很繁瑣,所以提供了一個HttpServlet類來解決這些問題,這個類繼承了GenericServlet類,除了能實現其所有方法,還根據HTTP請求的特性進行了擴充,使得其更能有效地處理基於HTTP協議的請求。

        6、HttpServlet類

        這個類的源碼有點長,不再詳細展示,有興趣可以去看源碼,這裡通過類的結構圖說明。

                其中HTTP協議的請求類型與其對應的實現方法見下表:

        該類繼承了GenericServlet類,用於接收基於Http協議的請求,並對請求進行處理,然後做出響應。一般在web開發中,開發者自己編寫的Servlet類只需要繼承HttpServlet類即可。這裡我們重點介紹兩個service()方法。

        service(ServletRequest req, ServletResponse res):通過源碼可以發現,此方法是GenericServlet類的service()方法的實現,他把ServletRequest和ServletResponse對象分別強制轉化為HttpServletRequest和HttpServletResponse對象,並把強制轉化後的對象作為參數,調用另一個重載的service(HttpServletRequest req, HttpServletResponse resp)方法。

        service(HttpServletRequest req, HttpServletResponse resp):通過源碼可以看出,這個方法會根據不同的HTTP請求類型(GET、POST或其他),調用不同的實現方法(doGet()、doPost()或其他)。這樣一來,當開發者自己編寫Servlet類時(繼承HttpServlet類),我們只需要覆蓋(重寫)doGet()、doPost()或其他doXXX()方法就可以了,而不需要覆蓋(重寫)service()方法,這樣就簡化了許多。實際上筆者在開發中遇到的幾個項目的servlet類中都是覆蓋(重寫)了doGet()、doPost()方法,而沒有覆蓋(重寫)service()方法。

        7、總結

        本篇著重介紹了和servlet相關的幾個比較重要的介面和類,下麵通過圖片說明它們之間的繼承關係:

        在實際的web項目中,如果需要開發者自己寫servlet類,一般直接繼承HttpServlet類即可。在用Tomcat載入servlet類時,如果需要初始化一些信息(比如解析web.xml文件中<servlet>標簽下的配置信息),可以覆蓋(重寫)無參的init()方法;如果要處理GET請求,可以覆蓋(重寫)doGet()方法;如果要處理POST請求,可以覆蓋(重寫)doPost()方法。init()、doGet()、doPost()這三個方法是筆者在開發web項目中遇到最多的,基本上自己寫的servlet類裡面,都是繼承了HttpServlet類,覆蓋(重寫)了這三個方法。

        本篇就介紹到這裡了,希望對大家有所幫助。筆者能力有限,裡面難免有不准確或不正確的地方,歡迎各位指正。

        轉載請註明出處 http://www.cnblogs.com/Y-oung/p/8419644.html

        工作、學習、交流或有任何疑問,請聯繫郵箱:[email protected]  微信:yy1340128046


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過前面三篇的分析,我們深入瞭解了AbstractQueuedSynchronizer的內部結構和一些設計理念,知道了AbstractQueuedSynchronizer內部維護了一個同步狀態和兩個排隊區,這兩個排隊區分別是同步隊列和條件隊列。我們還是拿公共廁所做比喻,同步隊列是主要的排隊區,如果公 ...
  • 一、秒殺業務為什麼難做 IM系統,例如QQ或者微博,每個人都讀自己的數據(好友列表、群列表、個人信息)。 微博系統,每個人讀你關註的人的數據,一個人讀多個人的數據。 秒殺系統,庫存只有一份,所有人會在集中的時間讀和寫這些數據,多個人讀一個數據。 例如小米手機每周二的秒殺,可能手機只有1萬部,但瞬時進 ...
  • 相關內容: 繼承:多繼承、super、__init__、重寫父類變數或函數 多態 繼承: 在Python3中,不寫基類的類預設繼承object 繼承就是子類獲得了父類的全部功能:比如學生和老師都有“姓名,性別,年齡、ID”等學校人員屬性,如果學生和老師都直接繼承學校人員的“姓名,性別,年齡、ID”,... ...
  • 案例目標 簡單介紹 redis pipeline 的機制,結合一段實例說明pipeline 在提升吞吐量方面發生的效用。 案例背景 應用系統在數據推送或事件處理過程中,往往出現數據流經過多個網元; 然而在某些服務中,數據操作對redis 是強依賴的,在最近的一次分析中發現: 一次數據推送會對 red ...
  • 當多個類中出現同一個功能,但是具體的主體功能不同,這時可以進行向上抽取,只抽取功能定義,主體功能由特定類實現。 上面這個類使用abstract關鍵字進行區分 抽象類的特點: 1、抽象方法一定在抽象類中。 2、抽象方法和抽象類都必須被abstract關鍵字修飾。 3、抽象類不可以使用new創建對象,因 ...
  • 所謂的JSP(Java Server Page)就是指在HTML中嵌入大量的Java代碼而已。 JSP註釋 顯示註釋(允許客戶端點擊查看源碼看到) <!-- 註釋內容 -->(HTML註釋) 隱式註釋(客戶端無法看見) // 註釋:單行註釋(Java註釋) /* 註釋 */:多行註釋(Java註釋) ...
  • 追新番網站提供最新的日劇和日影下載地址,更新比較快。 個人比較喜歡看日劇,因此想著通過爬取該網站,做一個資源地圖 可以查看網站到底有哪些日劇,並且隨時可以下載。 ...
  • 2.1語法 public 返回值類型 方法名(){ //方法體 } 2.2方法的調用語法 對象名.方法名 計算平均分和總成績 1 public class Score { 2 /** 3 * 創建類 ScoreCalc 編寫方法實現各功能 編寫測試類 4 * 從鍵盤接收三門課分數,(java c# ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...