初學(xué)Java Web(3)——第一個Servlet

這學(xué)期 Java Web 課程的第一節(jié)課就簡短復(fù)習(xí)了一下 Java 的一些基礎(chǔ)知識,所以覺得 Java 的基礎(chǔ)知識還是很重要的,但當(dāng)我想要去寫一篇 Java 回顧的文章的時候發(fā)現(xiàn)很難,因為坑實在太多了(一個頭,兩個大),只能另外找一些時間去寫順便鞏固鞏固自己的基礎(chǔ)。

——【1. 什么是 Servlet 】——

學(xué)習(xí)一個東西就要先去了解它是什么東西。

Servlet 取自兩個單詞:Server、Applet (很符合 sun 公司的命名特點), Java Servlet 的簡稱,其實質(zhì)就是運行在 Web 應(yīng)用服務(wù)器上的 Java 程序,與普通 Java 程序不同,它是位于 Web 服務(wù)器內(nèi)部的服務(wù)器端的 Java 應(yīng)用程序,可以對 Web 瀏覽器或其他 HTTP 客戶端程序發(fā)送的請求進行處理。

狹義的Servlet是指Java語言實現(xiàn)的一個接口,廣義的Servlet是指任何實現(xiàn)了這個Servlet接口的類,一般情況下,人們將Servlet理解為后者。Servlet運行于支持Java的應(yīng)用服務(wù)器中。從原理上講,Servlet可以響應(yīng)任何類型的請求,但絕大多數(shù)情況下Servlet只用來擴展基于HTTP協(xié)議的Web服務(wù)器。

實際上,Servlet 就像是一個規(guī)范,想象一下我們的 USB 接口,它不僅約束了U盤的大小和形狀,同樣也約束了電腦的插槽,Servlet 也是如此,它不僅約束了服務(wù)器端如何實現(xiàn)規(guī)范,也約束著 Java Web 項目的結(jié)構(gòu),為什么這樣說,我們下面再來講,編寫一個 Servlet 其實就是按照 Servlet 規(guī)范編寫一個 Java 類。

——【2. Servlet 與 Servlet 容器 】——

Servlet 對象與普通的 Java 對象不同,它可以處理 Web 瀏覽器或其他 HTTP 客戶端程序發(fā)送的 HTTP 請求,但前提是把 Servlet 對象布置到 Servlet 容器中,也就是說,其運行需要 Servlet 容器的支持。

Servlet 容器也叫做 Servlet 引擎,是 Web 服務(wù)器或應(yīng)用程序服務(wù)器的一部分,用于在發(fā)送的請求和響應(yīng)之上提供網(wǎng)絡(luò)服務(wù),解碼基于 MIME 的請求,格式化基于 MIME 的響應(yīng)。Servlet 沒有 main 方法,不能獨立運行,它必須被部署到 Servlet 容器中,由容器來實例化和調(diào)用 Servlet 的方法(如 doGet() 和 doPost() 方法),Servlet 容器在 Servlet 的生命周期內(nèi)包容和管理 Servlet 。在 JSP 技術(shù) 推出后,管理和運行 Servlet / JSP 的容器也稱為 Web 容器。

有了 Servlet 之后,用戶通過單擊某個鏈接或者直接在瀏覽器的地址欄中輸入 URL 來訪問 Servlet ,Web 服務(wù)器接收到該請求后,并不是將請求直接交給 Servlet ,而是交給 Servlet 容器。Servlet 容器實例化 Servlet ,調(diào)用 Servlet 的一個特定方法對請求進行處理, 并產(chǎn)生一個響應(yīng)。這個響應(yīng)由 Servlet 容器返回給 Web 服務(wù)器,Web 服務(wù)器包裝這個響應(yīng),以 HTTP 響應(yīng)的形式發(fā)送給 Web 瀏覽器。

Servlet 容器能提供什么?

上面我們知道了需要由 Servlet 容器來管理和運行 Servlet ,但是為什么要這樣做呢?使用 Servlet 容器的原因有:

  1. 通信支持:利用容器提供的方法,你能輕松的讓 Servlet 與 web 服務(wù)器對話,而不用自己建立 serversocket 、監(jiān)聽某個端口、創(chuàng)建流等。容器知道自己與 web 服務(wù)器之間的協(xié)議,所以你的 Servlet 不用擔(dān)心 web 服務(wù)器(如Apache)和你自己的 web 代碼之間的 API ,只需要考慮如何在 Servlet 中實現(xiàn)業(yè)務(wù)邏輯(如處理一個訂單)。
  2. 生命周期管理: Servlet 容器控制著 Servlet 的生與死,它負(fù)責(zé)加載類、實例化和初始化 Servlet ,調(diào)用 Servlet 方法,以及使 Servlet 實例被垃圾回收,有了 Servlet 容器,你不需要太多的考慮資源管理。
  3. 多線程支持:容器會自動為它所接收的每個 Servlet 請求創(chuàng)建一個新的 java 線程。針對用戶的請求,如果 Servlet 已經(jīng)運行完相應(yīng)的http服務(wù)方法,這個線程就會結(jié)束。這并不是說你不需要考慮線程安全性,其實你還會遇到同步問題,不過這樣能使你少做很多工作。
  4. 聲明方式實現(xiàn)安全:利用 Servlet 容器,你可以使用 xml 部署描述文件來配置和修改安全性,而不必將其硬編碼寫到 Servlet 類代碼中。
  5. JSP支持: Servlet容器負(fù)責(zé)將 jsp 代碼翻譯為真正的 java 代碼。

Servlet 生命周期

通常情況下,Servlet 容器也就是指 Web 容器,如 Tomcat、Jboss、Resin、Weblogic 等,它們對 Servlet 進行控制。當(dāng)一個客戶端發(fā)送 HTTP 請求時,由容器加載 Servlet 對其進行處理并做出響應(yīng)。在 Web 容器中,Servlet 主要經(jīng)歷 4 個階段,如下圖:

Servlet 與容器

Servlet 與 Web 容器的關(guān)系是非常密切的,在 Web 容器中 Servlet 主要經(jīng)歷了 4 個階段,這 4 個階段實質(zhì)是 Servlet 的生命周期,由容器進行管理。

(1)在 Web 容器啟動或者客戶機第一次請求服務(wù)時,容器將加載 Servlet 類并將其放入到 Servlet 實例池。

(2)當(dāng) Servlet 實例化后,容器將調(diào)用 Servlet 對象的 init() 方法完成 Servlet 的初始化操作,主要是為了讓 Servlet 在處理請求之前做一些初始化工作。

(3)容器通過 Servlet 的 service() 方法處理客戶端請求。在 Service() 方法中,Servlet 實例根據(jù)不同的 HTTP 請求類型作出不同處理,并在處理之后作出相應(yīng)的響應(yīng)。

(4)在 Web 容器關(guān)閉時,容器調(diào)用 Servlet 對象的 destroy() 方法對資源進行釋放。在調(diào)用此方法后,Servlet 對象將被垃圾回收器回收。

——【3. 第一個 Servlet 】——

① 搭建 Java Web 項目

  1. 創(chuàng)建 一個 Java 項目,并命名為 HelloServlet; (注意:這是普通的 Java 項目而不是動態(tài) Web 項目)
  2. 在項目的根目錄下創(chuàng)建一個文件夾 webapp,表示 Web 項目的根;
  3. 在 webapp 中創(chuàng)建 WEB-INF 文件夾;
  4. 在 WEB-INF 文件夾中創(chuàng)建文件夾:classes,lib;
  5. 在 WEB-INF 文件中添加 Tomcat 根目錄下 conf 文件夾中的 web.xml 文件;(只保留根元素,就像下面這樣)
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                          http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
      version="3.1">
    
    </web-app>
    
    
  6. 把當(dāng)前項目的 classpath 路徑改成 webapp/WEB-INF 下的 classes 中。

② 編寫 Servlet

  1. 為該項目增加Servlet的支持.
    1.1. 把Tomcat根/lib中servlet-api.jar文件拷貝到項目下WEB-INF下的lib中
    1.2. 在項目中選擇servlet-api.jar,鼠標(biāo)右鍵,build path-->add to build path
  1. 開發(fā)Servlet程序:
    2.1:定義一個類HelloServlet,并讓該類去實現(xiàn)javax.servlet.Servlet接口;
    2.2:實現(xiàn)Servlet接口中的init,service,destory等方法.
import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloServlet implements Servlet{
    @Override
    public void init(ServletConfig config) throws ServletException {
    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("測試一下!");     // 先在這里寫下測試代碼
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    }

}

注意:若生成方法中的參數(shù)是 arg0 或則 arg1 等格式的,原因是還沒有關(guān)聯(lián)源代碼的問題: 關(guān)聯(lián)上 tomcat src 文件即可

③ 配置 Servlet

上面編寫好的 HelloServlet 類僅僅是一個普通的實現(xiàn)類而已,而現(xiàn)在我想要它運行在我自己的 Tomcat 服務(wù)器中,所以應(yīng)該通知 Tomcat 服務(wù)器來管理我的 HelloServlet 類,具體的做法如下:

  1. 找到項目根下的WEB-INF下的web.xml文件:

  2. 在根元素web-app中創(chuàng)建一個新的元素節(jié)點:servlet

  3. 在根元素web-app中創(chuàng)建一個新的元素節(jié)點:servlet-mapping(Servlet 的映射)

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                          http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
      version="3.1">
      
    
        <servlet>
            <servlet-name>HelloServlet</servlet-name>
            <servlet-class>lt.HelloServlet</servlet-class>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    web.xml 提供路徑和servlet映射關(guān)系,這意思是把/hello這個路徑,映射到 HelloServlet 這個類上,需要注意的是:< servlet> 標(biāo)簽下的 < servlet-name>與 < servlet-mapping> 標(biāo)簽下的 < servlet-name> 必須一樣(因為標(biāo)簽被編輯器識別故<后加了一個空格)

  4. 配置 Tomcat 服務(wù)器:

    4.1. 修改默認(rèn)端口為 80 端口:
    首先進入到 Tomcat 服務(wù)器的根路徑下找到 conf 文件夾下的 server.xml 文件,默認(rèn)是在第 70 行,找到 Connector 元素的 port 屬性,修改為 80 ,重啟 Tomcat 即可。


    Tomcat 的默認(rèn)端口為8080,而 HTTP 協(xié)議的默認(rèn)端口是 80,配置 80 端口的好處在于,我們平時輸入的類似于 http://baidu.com 其實是默認(rèn)省略了寫 80端口的,它其實等價于:http://baidu.com:80/ ,所以以后我們就不用再寫冒號直接輸入 locahost 就能進入到 Tomcat 的配置頁面了。

    4.2 部署 Java 項目(告訴 Tomcat 服務(wù)器來管理我們的項目):
    這里直接引用 how2j.cn 的教程啦:


所以加上<Context path="" docBase="F:\\Projects\\JavaProject\\HelloServlet\\webapp" />這一句重啟 Tomcat 服務(wù)器

在瀏覽器中輸入 localhost/hello,回車,即可在 Tomcat 服務(wù)器上看到相關(guān)信息,至此第一個 Servlet 就編寫成功了

——【4. Servlet 請求過程】——

學(xué)習(xí) Servlet 技術(shù),就需要有一個 Servlet 運行環(huán)境,也就是需要有一個 Servlet 容器,如這里使用的【Tomcat】

Tomcat 服務(wù)器接受客戶請求并做出響應(yīng)的過程如下(以上面搭建的項目為例):

① 打開瀏覽器發(fā)起請求:http://localhost:80/hello/index.html (假設(shè)有一個 index.html 文件)

② 服務(wù)器接收到請求后處理請求:

htpp:所使用的協(xié)議
localhost:ip地址,確定訪問的主機
80:端口號
hello:上下文路徑,確定訪問項目的根路徑
index.html:確定訪問項目中的具體哪一個資源

③ 根據(jù) hello 去 tomcat/conf/server.xml 文件中找到相關(guān)配置文件,根據(jù)上下文路徑找到項目的根路徑:
<Context path="" docBase="F:\\Projects\\JavaProject\\HelloServlet\\webapp" />
如果找不到根路徑(因為這里默認(rèn)上下文路徑為空),返回 404

④ 根據(jù)資源名稱去項目中的 web.xml 文件中找到相關(guān)的配置,找到配置中的<url-pattern>

如果找不到 hello 的資源名稱,則返回 404

⑤ 根據(jù)資源名稱找到 Servlet 的全限定名,如果找不到則在啟動服務(wù)器的時候報錯
java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name HelloServlet

⑥ 根據(jù)找到的全限定名創(chuàng)建對象,在創(chuàng)建對象之前需要判斷是否是第一次請求,使用 Tomcat 中使用 Servlet 實例緩存池來實現(xiàn),若是第一次則調(diào)用對象的 init 方法。

⑦ 創(chuàng)建 req,resp 對象,執(zhí)行 service 方法;

⑧ 使用 resp 對象給瀏覽器響應(yīng)信息。

發(fā)現(xiàn)一邊學(xué)一邊寫起來太麻煩了,一方面是因為自己的水平,另一方面是覺得這樣太費時間了,也要開始找實習(xí)了,所以時間有些寶貴,可能這不會作為一個連續(xù)的系列,反而是一些學(xué)習(xí)的分享和感悟,emmm....事實上,Servlet也還有好多東西,包括最新支持注解方式配置等....
參考資料:
《Java Web程序設(shè)計 慕課版——明日科技》
how2j.cn
理解Servlet和Servlet容器、Web服務(wù)器等概念


歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz
分享自己的學(xué)習(xí) & 學(xué)習(xí)資料 & 生活
想要交流的朋友也可以加qq群:3382693

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,695評論 2 370

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

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,313評論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,775評論 18 139
  • 轉(zhuǎn)自陳明乾的博客,可能有一定更新。 轉(zhuǎn)原文聲明:原創(chuàng)作品,允許轉(zhuǎn)載,轉(zhuǎn)載時請務(wù)必以超鏈接形式標(biāo)明文章 原始出處 、...
    C86guli閱讀 4,711評論 6 72
  • 0 系列目錄# WEB請求處理 WEB請求處理一:瀏覽器請求發(fā)起處理 WEB請求處理二:Nginx請求反向代理 本...
    七寸知架構(gòu)閱讀 14,000評論 22 190
  • 飛紅粉浪秋千里,不解春愁。不解春愁,心向山林更探幽。 江南陌上陽夫子,偏愛風(fēng)流。偏愛風(fēng)流,醉臥瓊花落白頭。 (詞林...
    瑾檀yuying閱讀 949評論 31 48