Servlet必知必會

Servlet簡述

Servlet 是一個 Java 類新症,通常在 Web 應用 MVC 模式中擔任 Controler 角色乾闰,它的任務是得到一個客戶的請求庐冯,再發(fā)回一個響應,在接受客戶請求后迹淌,調用模型對請求數據進行處理,將處理后的數據設置為請求屬性己单,再發(fā)送到控制頁面的 JSP 中唉窃。下面就通過一次完整的HTTP請求來介紹 Servlet 是如何工作的。

一次HTTP請求的到來

容器全盤控制著 Servlet 的一生纹笼,當用戶點擊一個鏈接比如:http://localhost:8080/testWeb/action.do 后纹份,這個請求到達服務器和容器,Tomcat看到用戶請求的是 testWeb 這個Web應用廷痘,于是到 testWeb 目錄下去找 Web.xml (我們一般稱之為部署描述文件,即DD)蔓涧,在DD中找 servlet-mapping 元素,與之匹配的 url-pattern,根據這個 url-pattern 的 servlet-name 映射到真正的 servlet-class 笋额,容器根據此依據調用相應的 Servlet 類元暴。

    <servlet>
        <servlet-name>ActionServletName</servlet-name>
        <servlet-class>com.gyf.web.ActionServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ActionServletName</servlet-name>
        <url-pattern>/action.do</url-pattern>
    </servlet-mapping>

Servlet 的生命周期

通過上述過程,容器找到了應該調用的 Servlet 兄猩,如果這個 Servlet 類還沒有被加載茉盏,容器會從頭調用Servlet 的生命周期:

  1. 首先加載目標類(ActionServlet.class),接著調用Servlet的默認無參構造函數(注意我們不需要去覆蓋Servlet的構造函數)。
  1. 接著調用 init() 方法枢冤,這個方法在 Servlet 的一生中只調用一次援岩,如果你有其他的初始化代碼(如得到一個數據庫連接)。
  2. 接著調用 Service()方法掏导,如果容器當初發(fā)現 Servlet 類已經被加載就會跳過前面兩個步驟直接進入這個步驟享怀,每次有HTTP請求到來時,都會調用目標 Servlet 的Service 方法趟咆,這個Service方法每次調用都會開啟一個新線程添瓷,根據HTTP請求的類型決定是繼續(xù)調用doGet(),還是doPost()梅屉。Service 方法在 Servlet 的一生中可以調用多次。
  3. 最后調用destroy()方法殺死這個 Servlet 類鳞贷,在這個方法中可以進行垃圾回收清理資源坯汤。
Servlet生命周期

注意在每個JVM上,每個特定的 Servlet 類只會有一個實例搀愧,所以不存在對于Servlet的每個實例這種說法惰聂。

Servlet 的繼承結構和方法

ServletConfig 與 ServletContext

我們在 Servlet 輸出一些固定信息時,可能會這樣做

PrintWriter out=response.getWriter();
out.println("59833576*@qq.com");

如果我們要修改郵箱地址怎么辦咱筛,就只有修改源代碼搓幌,停止 Web 應用,重新編譯迅箩,再啟動 Web 應用溉愁。非常繁瑣,在實際生產環(huán)境中饲趋,能不去動源代碼就不去動源代碼拐揭,那么我們可以用 ServletConfig 與 ServletContext 來解決這個問題。

ServletConfig

在部署描述文件中這樣寫:

<servlet>
    <servlet-name>ActionServletName</servlet-name>
    <servlet-class>com.gyf.web.ActionServlet</servlet-class>
    <init-param>
        <param-name>adminEmail</param-name>
        <param-value>59833576*@qq.com</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>ActionServletName</servlet-name>
    <url-pattern>/action.do</url-pattern>
</servlet-mapping>

可以看到 init-param 是在 servlet 標簽內的奕塑,這也意味著只能在該 servlet 類中使用堂污,并不是全局的。

在 Servlet 中我們這么使用:

out.println(getServletConfig().getInitParameter("adminEmail"));

注意龄砰,不能在構造函數中調用這個方法敷鸦,在init()后,Servlet 才得到ServletConfig對象寝贡。

ServletContext

ServletContext是全局有效的,這一點從它的部署位置就可以看出來:

<web-app 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
    <servlet>
        <servlet-name>Test</servlet-name>
        <servlet-class>com.gyf.web.GetJarServlet</servlet-class>
    </servlet>
  
    <servlet-mapping>
        <servlet-name>Test</servlet-name>
        <url-pattern>/servlet-api.jar</url-pattern>
    </servlet-mapping>
  
    <context-param>
        <param-name>adminEmail</param-name>
        <param-value>59833576*@qq.com</param-value>
    </context-param>

</web-app>

context-param 就在web-app 標簽下值依,所以它對所有的 Servlet 都是有效的圃泡,在 Servlet 代碼中:

out.println(getServletContext().getInitParamter("adminEmail"));

要注意區(qū)分ServletContext 和 ServletConfig的區(qū)別和寫法。

監(jiān)聽者Listener

如果我們想在應用部署時就馬上做一個事情要怎么做呢愿险?這是我們就需要一個監(jiān)聽者颇蜡。監(jiān)聽者分為很多種,每種的用途用法都不一樣辆亏,比如剛才說的應用部署時就要做一個事情就需要 ServletContextListener风秤。

ServletContextListener

package com.gyf;
import javax.servlet.*;

public class MyServletContextListener implements ServletContextListener
{
    public void contextInitialized(ServletContextEvent event)
    {
        ServletContext sc=event.getServletContext();
        String dogBreed=sc.getInitParameter("breed");
        Dog d=new Dog(dogBreed);
        sc.setAttribute("dog",d);
        //得到數據庫連接
        //將數據保存進數據庫
    }
    public void contextDestroyed(ServletContextEvent event)
    {
        //關閉數據庫
    }
}

方法很簡單,我們只需要擴展 ServletContextListener 接口就行了扮叨,并將這個 .class文件 放進classes文件夾缤弦,最后在部署描述文件中寫上該監(jiān)聽類的名字就行了:

<listener>
        <listener-class>
            com.gyf.MyServletContextListener
        </listener-class>
    </listener>

還有很多監(jiān)聽者類可供使用

上下文初始化參數線程安全

現在有了一個問題,既然 ServletContext 是全局可見的彻磁,那么如何保證保證其線程安全呢碍沐?有的同學可能會想在 doPost() 或 doGet() 方法上加 synchronized 狸捅,但是仔細想一想,這樣做只能保證每個Servlet 只有一個線程在運行累提,但是一個Web應用可以有很多個Servlet尘喝,這樣的話仍然不能保證它的線程安全。正確方法應該是這樣做的:

synchronized (getServletContext())
{
    getServletContext().setAttribute("foo",22);
    getServletContext().setAttribute("bar",42);
}

每次使用ServletContext都要求先獲得它的鎖斋陪,這種方法才奏效

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末朽褪,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子无虚,更是在濱河造成了極大的恐慌缔赠,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骑科,死亡現場離奇詭異橡淑,居然都是意外死亡,警方通過查閱死者的電腦和手機咆爽,發(fā)現死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門梁棠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斗埂,你說我怎么就攤上這事符糊。” “怎么了呛凶?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵男娄,是天一觀的道長。 經常有香客問我漾稀,道長模闲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任崭捍,我火速辦了婚禮尸折,結果婚禮上,老公的妹妹穿的比我還像新娘殷蛇。我一直安慰自己实夹,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布粒梦。 她就那樣靜靜地躺著亮航,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匀们。 梳的紋絲不亂的頭發(fā)上缴淋,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音,去河邊找鬼宴猾。 笑死圆存,一個胖子當著我的面吹牛,可吹牛的內容都是我干的仇哆。 我是一名探鬼主播沦辙,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讹剔!你這毒婦竟也來了油讯?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤延欠,失蹤者是張志新(化名)和其女友劉穎陌兑,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體由捎,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡兔综,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了狞玛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片软驰。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖心肪,靈堂內的尸體忽然破棺而出锭亏,到底是詐尸還是另有隱情,我是刑警寧澤硬鞍,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布慧瘤,位于F島的核電站,受9級特大地震影響固该,放射性物質發(fā)生泄漏锅减。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一伐坏、第九天 我趴在偏房一處隱蔽的房頂上張望怔匣。 院中可真熱鬧,春花似錦著淆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呐矾,卻和暖如春苔埋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜒犯。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工组橄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荞膘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓玉工,卻偏偏與公主長得像羽资,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子遵班,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容