Servlet前置知識

動態(tài)頁面和靜態(tài)頁面

介紹 Servlet 之前,先來了解 靜態(tài)頁面、動態(tài)頁面 的區(qū)別:

  • 靜態(tài)頁面:或稱為靜態(tài)資源,一般除了 php、asp、jsp、cgi 等文件外,其它的都是靜態(tài)資源。如常見的 html、css、js、png、gif、gzip 文件。用戶訪問某個靜態(tài)資源時,web 服務(wù)器進行的操作很簡單,就是添加適當(dāng)?shù)?HTTP 響應(yīng)頭部,然后一個空行,表示頭部結(jié)束,最后去磁盤中讀取這個文件,將讀取到的數(shù)據(jù)追加到這個空行的后面,同時將 HTTP 響應(yīng)數(shù)據(jù)發(fā)送給瀏覽器,也就是一個簡單的文件傳輸過程,僅此而已。

  • 動態(tài)頁面:與靜態(tài)資源不同,對于 php、asp、jsp、cgi 等動態(tài)頁面,web 服務(wù)器不再是簡單的去磁盤讀取這些文件,然后將其發(fā)送給瀏覽器(如果是這樣的,那我們訪問 php 頁面得到的將是該頁面的 php 源碼,而不是執(zhí)行后的輸出),而是先運行這些 php、asp、jsp、cgi 程序,獲取它們的輸出,最后將輸出結(jié)果發(fā)送給瀏覽器。也就是說,這些響應(yīng)數(shù)據(jù)是程序運算后動態(tài)生成的,不再是簡單的文件傳輸了。

CGI協(xié)議

那么我們該如何編寫動態(tài)頁面呢?也就是說,我們該如何將編寫的程序與 web 服務(wù)器進行交互,來動態(tài)的生成 web 內(nèi)容呢?最簡單的方式就是 CGI 了。CGI 是 Common Gateway Interface 的縮寫,即 通用網(wǎng)關(guān)接口。CGI 不是一門編程語言,它只是規(guī)定 web 服務(wù)器與執(zhí)行程序之間如何通信的一個協(xié)議。CGI 是獨立于任何語言的,CGI 程序可以使用任何腳本語言或者是完全獨立的編程語言實現(xiàn),只要這個語言可以在當(dāng)前系統(tǒng)上運行。比如 Python、Perl、PHP、Shell、C/C++ 等等(其實 Java 也是可以的,不過要借助 Shell 腳本)。

使用 CGI 編寫動態(tài)頁面是非常簡單的,但是,這并不是說 CGI 就完美了,事實上,它有很多缺點,以至于現(xiàn)在基本沒人使用 CGI 編寫動態(tài)頁面。為什么呢?最主要的問題就是 CGI 的 fork-and-execute 工作模式。每次訪問 CGI 頁面時,Web 服務(wù)器都要啟動一個新的 CGI 進程,然后服務(wù)完成后又退出。也就是說,當(dāng)前有多少個請求在線,就有多少個 CGI 進程在系統(tǒng)運行。這種工作模式在大規(guī)模的并發(fā)下,就會死翹翹了。

進一步的話可以采用進程池,但是進程池的消耗也是很大的,如果可以采取線程池的方式,那就更加完美了,這就是 Servlet 采取的方法,因為 Java 天生就支持多線程。

Servlet

Servlet(Server Applet),全稱 Java Servlet,未有中文譯文。是用 Java 編寫的服務(wù)器端程序。其主要功能在于交互式地瀏覽和修改數(shù)據(jù),動態(tài)生成 Web 內(nèi)容。狹義的 Servlet 是指 Java 語言實現(xiàn)的一個接口(javax.servlet.Servlet),廣義的 Servlet 是指任何實現(xiàn)了這個 Servlet 接口的類,一般情況下,人們將 Servlet 理解為后者。
Servlet 運行于支持 Java 的應(yīng)用服務(wù)器中(常用的有 Tomcat、WebLogic)。從實現(xiàn)上講,Servlet 可以響應(yīng)任何類型的請求,但絕大多數(shù)情況下 Servlet 只用來擴展基于 HTTP 協(xié)議的 Web 服務(wù)器。

為了更好的利用 Java 的優(yōu)勢,我們不再使用 Apache、Nginx 等 Web 服務(wù)器了,而是使用 Java 編寫的 Web 服務(wù)器。此 Java 服務(wù)器程序監(jiān)聽在 0.0.0.0:80 端口,維護一個線程池,等待客戶端的連接請求。當(dāng)有一個請求到達時,服務(wù)器程序從線程池中選擇一個空閑線程,執(zhí)行對應(yīng)的 Servlet 程序,當(dāng)有另一個請求到達時,也是從線程池中抽取一個空閑線程,執(zhí)行對應(yīng)的 Servlet 程序。執(zhí)行完畢后,這些線程不會立即銷毀,而是回到線程池中,等待新的任務(wù)到達。

而這個 Java 語言實現(xiàn)的 HTTP 服務(wù)器被稱為 應(yīng)用服務(wù)器,實際上,應(yīng)用服務(wù)器根本不用我們自己開發(fā),市面上有很多 Java 應(yīng)用服務(wù)器的實現(xiàn),有開源的(如 Tomcat),也有付費的(如 WebLogic)。因此,我們實際上要操心的只是 Servlet 而已。因為從始至終都只有應(yīng)用服務(wù)器這一個 Java 進程在系統(tǒng)運行,所以此方案占用的系統(tǒng)資源是非常少的,最大的資源消耗也就是線程池了。

注意,Java 應(yīng)用服務(wù)器只能執(zhí)行 Java 程序(比如這里的 Servlet,但實際上還有 Filter、Listener 等等),那么 靜態(tài)資源 該怎么處理呢?也是通過 Servlet 來處理,讓 Servlet 去磁盤中讀取這些靜態(tài)資源,然后發(fā)送回客戶端。也就是說,在 Java 應(yīng)用服務(wù)器中,靜態(tài)資源和動態(tài)資源都是要經(jīng)過 Servlet 處理的,這也帶來一個問題,在處理靜態(tài)資源時,Java 肯定是沒有 C、C++ 快速的,況且,Java 應(yīng)用服務(wù)器沒有 Apache、Nginx 這么多關(guān)于靜態(tài)資源的優(yōu)化參數(shù),就更慢了。所以,通常情況下,我們都是將 Apache/Nginx + Tomcat 兩者整合在一起,Apache/Nginx 在前,Tomcat 在后,所有 Web 請求都先到達 Apache/Nginx,Apache/Nginx 判斷是否為動態(tài)資源,如果是則交給后端的 Tomcat 處理,否則(靜態(tài)資源)直接使用 Apache/Nginx 處理。這樣的架構(gòu)下,靜態(tài)資源和動態(tài)資源的處理速度都非常好,兩全其美。

這里先理清楚幾個名詞,通常所說的 Servlet 是指實現(xiàn)了 javax.servlet.Servlet 接口的類,但是要運行這些 Servlet 類就必須要有一個專用的執(zhí)行環(huán)境,而提供這個環(huán)境的就是 Servlet 容器(其實就是一個普通的 Java 程序),目前有很多 Servlet 容器的實現(xiàn),比如開源的 Tomcat,但 Tomcat 不只包含 Servlet 容器,還包含其它一些組件,Tomcat 的 Servlet 容器有一個專有名稱 Catalina。而 Tomcat 又是 Apache 軟件基金會下屬的 Jakarta 項目開發(fā)的一個 Servlet 容器,因此你經(jīng)??吹竭@樣一個名詞 Apache Tomcat,其實就是指 Tomcat。

參考
https://www.zfl9.com/java-servlet.html#more

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容