Servlet第三篇【request和response簡介祥山、response的常見應(yīng)用】

Servlet的調(diào)用圖

前面我們已經(jīng)學(xué)過了Servlet的生命周期了圃验,我們根據(jù)Servlet的生命周期畫出Servlet的調(diào)用圖加深理解

image

Servlet的細(xì)節(jié)

一個(gè)已經(jīng)注冊(cè)的Servlet可以被多次映射

同一個(gè)Servlet可以被映射到多個(gè)URL上。


        <servlet>
            <servlet-name>Demo1</servlet-name>
            <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>/Demo1</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>/ouzicheng</url-pattern>
        </servlet-mapping>

無論我訪問的是http://localhost:8080/Demo1還是http://localhost:8080/ouzicheng缝呕。我訪問的都是Demo1澳窑。

image
image

Servlet映射的URL可以使用通配符

通配符有兩種格式:

  1. *.擴(kuò)展名
  2. 正斜杠(/)開頭并以“/*”結(jié)尾斧散。

匹配所有

image

匹配擴(kuò)展名為.jsp的

image

如果.擴(kuò)展名和正斜杠(/)開頭并以“/”結(jié)尾兩種通配符同時(shí)出現(xiàn),匹配的是哪一個(gè)呢摊聋?

  1. 看誰的匹配度高鸡捐,誰就被選擇
  2. *.擴(kuò)展名的優(yōu)先級(jí)最低

Servlet映射的URL可以使用通配符和Servlet可以被映射到多個(gè)URL上的作用:

  1. 隱藏網(wǎng)站是用什么編程語言寫的【.php,.net,.asp實(shí)際上訪問的都是同一個(gè)資源】
  2. 用特定的后綴聲明版權(quán)【公司縮寫】

         <servlet>
            <servlet-name>Demo1</servlet-name>
            <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.jsp</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.net</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.asp</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.php</url-pattern>
        </servlet-mapping>


Servlet是單例的

為什么Servlet是單例的

瀏覽器多次對(duì)Servlet的請(qǐng)求,一般情況下麻裁,服務(wù)器只創(chuàng)建一個(gè)Servlet對(duì)象箍镜,也就是說,Servlet對(duì)象一旦創(chuàng)建了煎源,就會(huì)駐留在內(nèi)存中色迂,為后續(xù)的請(qǐng)求做服務(wù),直到服務(wù)器關(guān)閉手销。

每次訪問請(qǐng)求對(duì)象和響應(yīng)對(duì)象都是新的

對(duì)于每次訪問請(qǐng)求脚草,Servlet引擎都會(huì)創(chuàng)建一個(gè)新的HttpServletRequest請(qǐng)求對(duì)象和一個(gè)新的HttpServletResponse響應(yīng)對(duì)象,然后將這兩個(gè)對(duì)象作為參數(shù)傳遞給它調(diào)用的Servlet的service()方法原献,service方法再根據(jù)請(qǐng)求方式分別調(diào)用doXXX方法馏慨。

線程安全問題

當(dāng)多個(gè)用戶訪問Servlet的時(shí)候,服務(wù)器會(huì)為每個(gè)用戶創(chuàng)建一個(gè)線程姑隅。當(dāng)多個(gè)用戶并發(fā)訪問Servlet共享資源的時(shí)候就會(huì)出現(xiàn)線程安全問題写隶。

原則:

  1. 如果一個(gè)變量需要多個(gè)用戶共享,則應(yīng)當(dāng)在訪問該變量的時(shí)候讲仰,加同步機(jī)制synchronized (對(duì)象){}
  2. 如果一個(gè)變量不需要共享慕趴,則直接在 doGet() 或者 doPost()定義.這樣不會(huì)存在線程安全問題

load-on-startup

如果在

image
image

作用:

  1. 為web應(yīng)用寫一個(gè)InitServlet,這個(gè)servlet配置為啟動(dòng)時(shí)裝載鄙陡,為整個(gè)web應(yīng)用創(chuàng)建必要的數(shù)據(jù)庫表和數(shù)據(jù)
  2. 完成一些定時(shí)的任務(wù)【定時(shí)寫日志冕房,定時(shí)備份數(shù)據(jù)】

在web訪問任何資源都是在訪問Servlet

當(dāng)你啟動(dòng)Tomcat,你在網(wǎng)址上輸入http://localhost:8080趁矾。為什么會(huì)出現(xiàn)Tomcat小貓的頁面耙册?

這是由缺省Servlet為你服務(wù)的

  • 我們先看一下web.xml文件中的配置,web.xml文件配置了一個(gè)缺省Servlet

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  • 什么叫做缺省Servlet毫捣?凡是在web.xml文件中找不到匹配的详拙,它們的訪問請(qǐng)求都將交給缺省Servlet處理,也就是說蔓同,缺省Servlet用于處理所有其他Servlet都不處理的訪問請(qǐng)求
  • 既然我說了在web訪問任何資源都是在訪問Servlet饶辙,那么我訪問靜態(tài)資源【本地圖片,本地HTML文件】也是在訪問這個(gè)缺省Servlet【DefaultServlet】
  • 證實(shí)一下:當(dāng)我沒有手工配置缺省Servlet的時(shí)候斑粱,訪問本地圖片是可以訪問得到的
image
  • 現(xiàn)在我自己配置一個(gè)缺省Servlet,Demo1就是我手工配置的缺省Servlet弃揽,覆蓋掉web.xml配置的缺省Servlet

    <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>zhongfucheng.web.Demo1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  • 下面我繼續(xù)訪問一下剛才的圖片,此時(shí)輸出的是Demo1這個(gè)Servlet寫上的內(nèi)容了
image
  • 總結(jié):無論在web中訪問什么資源【包括JSP】,都是在訪問Servlet矿微。沒有手工配置缺省Servlet的時(shí)候痕慢,你訪問靜態(tài)圖片,靜態(tài)網(wǎng)頁冷冗,缺省Servlet會(huì)在你web站點(diǎn)中尋找該圖片或網(wǎng)頁,如果有就返回給瀏覽器惑艇,沒有就報(bào)404錯(cuò)誤

ServletConfig對(duì)象

ServletConfig對(duì)象有什么用蒿辙?

通過此對(duì)象可以讀取web.xml中配置的初始化參數(shù)。

現(xiàn)在問題來了滨巴,為什么我們要把參數(shù)信息放到web.xml文件中呢思灌?我們可以直接在程序中都可以定義參數(shù)信息,搞到web.xml文件中又有什么好處呢恭取?

好處就是:能夠讓你的程序更加靈活【更換需求泰偿,更改配置文件web.xml即可,程序代碼不用改】

獲取web.xml文件配置的參數(shù)信息

  • 為Demo1這個(gè)Servlet配置一個(gè)參數(shù)蜈垮,參數(shù)名是name耗跛,值是zhongfucheng

    <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>zhongfucheng</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/Demo1</url-pattern>
    </servlet-mapping>
  • 在Servlet中獲取ServletConfig對(duì)象,通過ServletConfig對(duì)象獲取在web.xml文件配置的參數(shù)


    image

ServletContext對(duì)象

什么是ServletContext對(duì)象攒发?

當(dāng)Tomcat啟動(dòng)的時(shí)候调塌,就會(huì)創(chuàng)建一個(gè)ServletContext對(duì)象。它代表著當(dāng)前web站點(diǎn)

ServletContext有什么用惠猿?

  1. ServletContext既然代表著當(dāng)前web站點(diǎn)羔砾,那么所有Servlet都共享著一個(gè)ServletContext對(duì)象,所以Servlet之間可以通過ServletContext實(shí)現(xiàn)通訊偶妖。
  2. ServletConfig獲取的是配置的是單個(gè)Servlet的參數(shù)信息姜凄,ServletContext可以獲取的是配置整個(gè)web站點(diǎn)的參數(shù)信息
  3. 利用ServletContext讀取web站點(diǎn)的資源文件
  4. 實(shí)現(xiàn)Servlet的轉(zhuǎn)發(fā)【用ServletContext轉(zhuǎn)發(fā)不多,主要用request轉(zhuǎn)發(fā)】

Servlet之間實(shí)現(xiàn)通訊

ServletContext對(duì)象可以被稱之為域?qū)ο?/strong>

到這里可能有一個(gè)疑問趾访,域?qū)ο笫鞘裁茨靥恚科鋵?shí)域?qū)ο罂梢院唵卫斫獬?strong>一個(gè)容器【類似于Map集合】

實(shí)現(xiàn)Servlet之間通訊就要用到ServletContext的setAttribute(String name,Object obj)方法
第一個(gè)參數(shù)是關(guān)鍵字扼鞋,第二個(gè)參數(shù)是你要存儲(chǔ)的對(duì)象

  • 這是Demo2的代碼

        //獲取到ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        String value = "zhongfucheng";

        //MyName作為關(guān)鍵字屿聋,value作為值存進(jìn)   域?qū)ο蟆绢愋陀贛ap集合】
        servletContext.setAttribute("MyName", value);

  • 這是Demo3的代碼

        //獲取ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        //通過關(guān)鍵字獲取存儲(chǔ)在域?qū)ο蟮闹?        String value = (String) servletContext.getAttribute("MyName");

        System.out.println(value);
  • 訪問Demo3可以獲取Demo2存儲(chǔ)的信息,從而實(shí)現(xiàn)多個(gè)Servlet之間通訊
image

獲取web站點(diǎn)配置的信息

如果我想要讓所有的Servlet都能夠獲取到連接數(shù)據(jù)庫的信息藏鹊,不可能在web.xml文件中每個(gè)Servlet中都配置一下润讥,這樣代碼量太大了!并且會(huì)顯得非常啰嗦冗余盘寡。

  • web.xml文件支持對(duì)整個(gè)站點(diǎn)進(jìn)行配置參數(shù)信息所有Servlet都可以取到該參數(shù)信息

    <context-param>
        <param-name>name</param-name>
        <param-value>zhongfucheng</param-value>
    </context-param>
  • Demo4代碼

        //獲取到ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        //通過名稱獲取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);

image
  • 試一下Demo3是否能拿到楚殿,相同的代碼

        //獲取到ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        //通過名稱獲取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);
image

讀取資源文件

第一種方式:

  • 現(xiàn)在我要通過Servlet111讀取1.png圖片
image
  • 按我們以前的方式,代碼應(yīng)該是這樣的。

        FileInputStream fileInputStream = new FileInputStream("1.png");
        System.out.println(fileInputStream);
  • 當(dāng)我們?cè)L問的時(shí)候脆粥,卻出錯(cuò)了砌溺!說找不到1.png文件
image
  • 這是為什么呢?我們以前讀取文件的時(shí)候变隔,如果程序和文件在同一包名规伐,可以直接通過文件名稱獲取得到的!匣缘,原因很簡單猖闪,以前我們寫的程序都是通過JVM來運(yùn)行的,而現(xiàn)在肌厨,我們是通過Tomcat來運(yùn)行的
  • 根據(jù)web的目錄規(guī)范培慌,Servlet編譯后的class文件是存放在WEB-INF\classes文件夾中的
image
  • 看到這里,我們知道了要進(jìn)入classes目錄中讀取文件柑爸,所以我們將代碼改成以下方式

        FileInputStream fileInputStream = new FileInputStream("D:\\zhongfucheng\\web\\WEB-INF\\classes\\zhongfucheng\\web\\1.png");
        System.out.println(fileInputStream);

  • 再去讀取時(shí)吵护,就發(fā)現(xiàn)可以獲取到文件了。
  • 但是現(xiàn)在問題又來了表鳍,我讀取文件的時(shí)候都要寫上絕對(duì)路徑馅而,這樣太不靈活了。試想一下譬圣,如果我將該讀取文件的模塊移到其他的web站點(diǎn)上用爪,我的代碼就又要修改了【因?yàn)閣eb站點(diǎn)的名字不一樣】
  • 我們通過ServletContext讀取就可以避免修改代碼的情況胁镐,因?yàn)镾ervletContext對(duì)象是根據(jù)當(dāng)前web站點(diǎn)而生成的
  • 代碼如下所示:

        //獲取到ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        //調(diào)用ServletContext方法獲取到讀取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/zhongfucheng/web/1.png");
image

第二種方式:

  • 如果我的文件放在web目錄下偎血,那么就簡單得多了!,直接通過文件名稱就能獲取
image
  • 代碼如下所示

        //獲取到ServletContext對(duì)象
        ServletContext servletContext = this.getServletContext();

        //調(diào)用ServletContext方法獲取到讀取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("2.png");
image

第三種方式:

通過類裝載器讀取資源文件盯漂。

  • 我的文件放在了src目錄下【也叫做類目錄】
image
  • 代碼如下所示

        //獲取到類裝載器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通過類裝載器獲取到讀取文件流
        InputStream inputStream = classLoader.getResourceAsStream("3.png");

image
  • 我的文件放在了src目錄下的包下
image
  • 代碼如下颇玷,添加包名路徑即可。

        //獲取到類裝載器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通過類裝載器獲取到讀取文件流
        InputStream inputStream = classLoader.getResourceAsStream("/zhongfucheng/web/1.png");

原則:如果文件太大就缆,就不能用類裝載器的方式去讀取帖渠,會(huì)導(dǎo)致內(nèi)存溢出


如果文章有錯(cuò)的地方歡迎指正,大家互相交流竭宰。習(xí)慣在微信看技術(shù)文章的同學(xué)空郊,可以關(guān)注微信公眾號(hào):Java3y

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市切揭,隨后出現(xiàn)的幾起案子狞甚,更是在濱河造成了極大的恐慌,老刑警劉巖廓旬,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哼审,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)涩盾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門十气,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人春霍,你說我怎么就攤上這事砸西。” “怎么了址儒?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵芹枷,是天一觀的道長。 經(jīng)常有香客問我离福,道長杖狼,這世上最難降的妖魔是什么炼蛤? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任妖爷,我火速辦了婚禮,結(jié)果婚禮上理朋,老公的妹妹穿的比我還像新娘絮识。我一直安慰自己,他們只是感情好嗽上,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布次舌。 她就那樣靜靜地躺著,像睡著了一般兽愤。 火紅的嫁衣襯著肌膚如雪彼念。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天浅萧,我揣著相機(jī)與錄音逐沙,去河邊找鬼。 笑死洼畅,一個(gè)胖子當(dāng)著我的面吹牛吩案,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帝簇,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼徘郭,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了丧肴?” 一聲冷哼從身側(cè)響起残揉,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芋浮,沒想到半個(gè)月后冲甘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年江醇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了濒憋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陶夜,死狀恐怖凛驮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情条辟,我是刑警寧澤黔夭,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站羽嫡,受9級(jí)特大地震影響本姥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杭棵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一婚惫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魂爪,春花似錦先舷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撩笆,卻和暖如春捺球,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夕冲。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工氮兵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耘擂。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓胆剧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親醉冤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秩霍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容