91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Servlet及Servlet容器的概念以及使用注意點

發布時間:2021-11-10 09:44:52 來源:億速云 閱讀:233 作者:柒染 欄目:大數據

如何理解Servlet及Servlet容器的概念以及使用注意點,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

Servlet

Servlet是一個服務器端編程的組件,主要能力產生動態的數據內容,和任何java組件一樣,Servlet也是平臺不相關的。 Servlet的運行依賴于一個容器 (或者叫servlet engine),容器在運行時會把Servlet字節碼加載到虛擬機中生存一個servlet實例,并負責管理servlet實例的生命周期。

和servlet交互的對面可以是一個web瀏覽器,也可以是任何一個支持http協議的客戶端程序,客戶端和Servlet之間交互遵循request/response模式進行,實際上Servlet設計為并不僅僅局限于http協議,任何基于request/response的協議Servlet都支持。

Servlet容器

Servlet容器為servlet提供運行環境,servlet容器通常實現為一個Web服務器或者應用服務器的一部分。

Servlet容器的核心功能是接受請求、解碼請求內容,然后把解析后請求內容分發到相關的某個Servlet,Servlet處理后,容器會把Servlet返回的數據內容進行編碼并發送給客戶端。這個過程中容器可以在把請求分發給servlet之前修改請求內容,也可以在把servlet的返回內容發送到客戶端之前修改響應內容。

Servlet容器必須要提供http 1.0/1.1的支持,也可以支持https。

Servlet有完整的生命周期

一個servlet的生命周期階段主要包括:加載并創建servlet實例、初始化servlet實例、處理請求以及銷毀。

servlet的生命周期階段完全由servlet容器來管理,從編程的角度看生命周期主要體現在Servlet接口中定義的三個方法:

  • init方法,讓應用程序有機會執行初始化

  • service方法,應用程序處理請求并響應內容的地方

  • destroy方法,讓應用程序有機會釋放servlet持有的各種資源

任何一個servlet都必須直接或者間接實現這三個方法。 Servlet實例則由容器負責實例化,不需要應用程序參與,容器可以在啟動完成后就開始加載servlet,也可以在第一次servlet被選中處理請求時才加載此servlet。

servlet容器完成servlet的實例化后就開始進行初始化,容器會調用 init 方法并傳遞一個 ServletConfig 對象的引用,通過ServletConfig引用可以在Servlet中感知到Servlet的一些詳細配置參數和代表應用程序的ServletContext引用。一個servlet實例整個生命周期過程中init方法只會被容器調用一次。

只有初始化完成的servlet才能進一步提供請求服務,如果init方法中拋出ServletException異常或者沒有在容器定義的時間內返回,則servlet容器認為初始化失敗,此servlet不能提供服務。init方法拋出的可能是一個UnavailableException異常,這個異常暗示容器此servlet目前不可用:永久性不可用或者臨時不可用,如果是臨時性不可用則UnavailableException應該帶上一個不可用預估時間秒數,這種情況下容器不會直接失敗,而是會阻塞預估的時長然后重新創建一個servlet實例并再次執行初始化。

servlet成功初始化后就可以處理請求了,容器會調用service方法,并傳遞ServletRequest和ServletResponse兩個引用,ServletRequest封裝了客戶端請求信息,用戶應用程序的則負責填充ServletResponse對象,service方法返回后流程被容器接管。

service方法如果拋出ServletException異常代表失敗,容器需要作出合適的下一步處理,sevlet規范定義如下過程:service方法如果拋出實際是一個UnavailableException異常則表示此servlet目前不可用,同樣有永久性不可用和臨時不可用兩種情況,如果是永久性不可用,則容器會調用servlet的destroy方法清理然后釋放此servlet,并給客戶端響應SC_NOT_FOUND(404)狀態;如果是臨時性不可用,則servlet容器在預估的不可用時間內會直接拒絕所有的匹配到此servlet的請求而直接響應SC_SERVICE_UNAVAILABLE(503)狀態,并響應一個 Retry-After header,容器也可以選擇忽略這兩種不可用的差別,直接當做是永久性不可用并清理釋放servlet對象。

一個servlet實例正常情況下應該是永久駐留在容器中,直到關閉容器時才會銷毀容器中的servlet實例。在清理一個servlet實例之前,容器總是會調用destroy方法,用戶通常可以在destroy方法中做一些資源清理、持久化等工作,一旦一個servlet的destroy方法被調用后,容器就會完全釋放它以便垃圾收集器回收。

用Servlet編程

通常我們要在應用程序中實現一個Servlet類的話,不需要直接實現Servlet接口,而是通過擴展GenericServlet,在http環境中的話就就可以擴展HttpServlet,GenericServlet對Servlet接口做了基本實現,只是預留了service方法需要用戶實現, GenericServlet的實現沒有綁定到任何具體的應用層協議,它是通用的。

在HTTP協議環境中,平臺還提供了一個HttpServlet的實現類,HttpServlet就擴展自GenericServlet,HttpServlet完成實現了service方法,service方法中的實現方式是根據不同的http動詞作了一些基本情況的判斷處理,然后把正常情況下的過程委托到幾個特定的http方法:doGet,doPost,doPut,...,絕大多數情況我們自己的Servlet實現類應該選擇擴展HttpServlet,并且不應該直接重寫service方法,而是應該重寫doXXX方法。

public class RequestParameterServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
        // …
    }
}

應該重寫無參數init方法

Servlet接口中定義的init方法帶有一個ServletConfig參數:

public void init(ServletConfig config) throws ServletException;

init方法在GenericServlet中做了一個基本實現:

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

在GenericServlet版本的init實現中,先把容器傳遞過來的ServletConfig引用保存下來,然后調用了一個無參數的init方法,這個無參數的int方法正是預留給用戶實現的,因此,不管我們的Servlet類是擴展了GenericServlet,還是擴展了HttpServlet,如果有初始化的需求,那么我們應該重寫GenericServlet中的無參數init方法。

多線程環境中的Servlet

通常情況下,容器只會為web descriptor中聲明的每個servlet創建一個實例,這意味著在多線程情況下,其service方法是并發狀態下運行,因此我們在實現service方法時要自己保證其線程安全性,通常的做法是不在Servlet實現類中使用共享字段,或者對service方法中的相關代碼段加鎖。

另一種方式是我們的Servlet類實現SingleThreadModel接口,SingleThreadModel是一個標識接口,servlet容器保證實現SingleThreadModel的servlet實例的service方法在同一時間只有一個線程訪問,容器的做法可能是在servlet實例上加鎖,容器也可能會為同一個Servlet類創建出多個實例并在容器中緩存它們,然后對每一個請求分發到其中一個空閑的servlet實例。但是并不推薦使用SingleThreadModel接口,因為SingleThreadModel方式并不能完全解決線程安全問題,例如session中的數據并不能保證線程安全,并且在servlet 2.4版本中已經廢棄。

如何處理請求的字符編碼

客戶端的所有請求數據,包括請求路徑,協議,請求頭以及請求內容等這些數據全部都被容器封裝在一個ServletRequest對象中,從ServletRequest對象中讀取請求內容時必須要知道數據是如何編碼的,否則就不可能正確解析請求數據。

由于目前大多數瀏覽器客戶端在發送請求時都沒有在Content-Type域中提供字符編碼的標記,因此servlet規范中明確要求所有servlet容器在讀取請求數據時應該默認使用“ISO-8859-1”來解析數據。如果客戶端沒有發送請求數據的編碼格式,規范定義調用getCharacterEncoding方法應該返回null。

如果客戶端沒有發送請求內容的編碼格式,并且如果容器設定的默認編碼和實際的請求內容編碼又不一致時,就會解析得到錯誤的數據,為了糾正這種情況ServletRequest另外供了一個setCharacterEncoding方法,編程人員可以調用此方法覆蓋容器提供的編碼格式來讀取數據,此方法的調用一定要在讀取任何請求內容之前,否則不會有效果。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

陆河县| 仁怀市| 瑞金市| 布拖县| 广宁县| 辽阳市| 马尔康县| 浠水县| 武乡县| 孟村| 进贤县| 巴楚县| 荆门市| 武安市| 东乌珠穆沁旗| 水城县| 乌鲁木齐县| 分宜县| 四会市| 旺苍县| 靖西县| 新龙县| 潜江市| 莱芜市| 昭觉县| 双桥区| 庄浪县| 邯郸市| 剑河县| 如东县| 台中县| 东明县| 恭城| 温州市| 临洮县| 开封县| 巴林左旗| 新田县| 黔西| 昆山市| 商丘市|