深入理解Java Servlet與Web容器之間的關(guān)系
原創(chuàng)【51CTO特稿】自從計算機軟件開發(fā)進入網(wǎng)絡(luò)時代,就開始涉及到通訊問題。在客戶/服務(wù)器(也叫C/S應(yīng)用)時期,每個軟件都有自己的客戶端和服務(wù)器端軟件。并且客戶端和服務(wù)器端之間的通訊協(xié)議差別也很大。后來隨著互聯(lián)網(wǎng)的發(fā)展,基于瀏覽器/服務(wù)器的應(yīng)用逐漸成為主流,通訊協(xié)議也統(tǒng)一到HTTP協(xié)議。但是,在HTTP協(xié)議之上,如何處理來自客戶端的請求信息,以及如何對請求進行回應(yīng),則經(jīng)歷了很長時間也沒有統(tǒng)一下來。目前,對于這個問題的解決方案主要有兩種,一個是CGI,另一個是Servlet。
CGI(Common Gateway Interface),通用網(wǎng)關(guān)接口
通用網(wǎng)關(guān)接口,簡稱CGI,是一種根據(jù)請求信息動態(tài)產(chǎn)生回應(yīng)內(nèi)容的技術(shù)。通過CGI,Web 服務(wù)器可以將根據(jù)請求不同啟動不同的外部程序,并將請求內(nèi)容轉(zhuǎn)發(fā)給該程序,在程序執(zhí)行結(jié)束后,將執(zhí)行結(jié)果作為回應(yīng)返回給客戶端。也就是說,對于每個請求,都要產(chǎn)生一個新的進程進行處理。因為每個進程都會占有很多服務(wù)器的資源和時間,這就導(dǎo)致服務(wù)器無法同時處理很多的并發(fā)請求。另外CGI程序都是與操作系統(tǒng)平臺相關(guān)的,雖然在互聯(lián)網(wǎng)爆發(fā)的初期,CGI為開發(fā)互聯(lián)網(wǎng)應(yīng)用做出了很大的貢獻,但是隨著技術(shù)的發(fā)展,開始逐漸衰落。
Servlet
Servlet最初是在1995年由James Gosling 提出的,因為使用該技術(shù)需要復(fù)雜的Web服務(wù)器支持,所以當(dāng)時并沒有得到重視,也就放棄了。后來隨著Web應(yīng)用復(fù)雜度的提升,并要求提供更高的并發(fā)處理能力,Servlet被重新?lián)炱?,并在Java平臺上得到實現(xiàn),現(xiàn)在提起Servlet,指的都是Java Servlet。Java Servlet要求必須運行在Web服務(wù)器當(dāng)中,與Web服務(wù)器之間屬于分工和互補關(guān)系。確切的說,在實際運行的時候Java Servlet與Web服務(wù)器會融為一體,如同一個程序一樣運行在同一個Java虛擬機(JVM)當(dāng)中。與CGI不同的是,Servlet對每個請求都是單獨啟動一個線程,而不是進程。這種處理方式大幅度地降低了系統(tǒng)里的進程數(shù)量,提高了系統(tǒng)的并發(fā)處理能力。另外因為Java Servlet是運行在虛擬機之上的,也就解決了跨平臺問題。如果沒有Servlet的出現(xiàn),也就沒有互聯(lián)網(wǎng)的今天。
在Servlet出現(xiàn)之后,隨著使用范圍的擴大,人們發(fā)現(xiàn)了它的一個很大的一個弊端。那就是為了能夠輸出HTML格式內(nèi)容,需要編寫大量重復(fù)代碼,造成不必要的重復(fù)勞動。為了解決這個問題,基于Servlet技術(shù)產(chǎn)生了JavaServet Pages技術(shù),也就是JSP。Servlet和JSP兩者分工協(xié)作,Servlet側(cè)重于解決運算和業(yè)務(wù)邏輯問題,JSP則側(cè)重于解決展示問題。Servlet與JSP一起為Web應(yīng)用開發(fā)帶來了巨大的貢獻,后來出現(xiàn)的眾多Java Web應(yīng)用開發(fā)框架都是基于這兩種技術(shù)的,更確切的說,都是基于Servlet技術(shù)的。
Java Servlet與Web容器之間的關(guān)系
Java是一種動態(tài)加載和運行的語言。也就是說當(dāng)應(yīng)用程序持有一個類的地址(CLASSPATH)和名稱(包名和類名)的情況下,可以在程序運行期間任何時候加載這個類,并創(chuàng)建和使用該類的對象。Servlet就是基于這個機制與Web容器融合在一起的。目前已知的所有支持Java Servlet的Web容器都是采用Java開發(fā)的。當(dāng)Web容器接收到來自客戶端的請求信息之后,會根據(jù)URL中的Web元件地址信息到Servlet隊列中查找對應(yīng)的Servlet對象,如果找到則直接使用,如果沒有找到則加載對應(yīng)的類,并創(chuàng)建對象。也就是說,Servlet對象是在第一次被使用的時候才創(chuàng)建的,并且一旦創(chuàng)建就會被反復(fù)使用,不再創(chuàng)建新的對象。所有創(chuàng)建出的Servlet對象會在Web服務(wù)器停止運行的時候統(tǒng)一進行垃圾回收。
為了解決客戶端請求地址與Java Servlet之間對應(yīng)關(guān)系問題,Web容器需要一個用來描述這種對應(yīng)關(guān)系的文件,一般是web.xml文件。如果一個Web應(yīng)用程序中存在很多個Servlet,那么web.xml會變得非常龐大。在Servlet 3.0規(guī)范推出之后,允許在Servlet代碼中使用聲明式語法來代替web.xml中的描述信息,這才讓web.xml瘦身下來。下圖是這個過程的一個示意圖。
在這個圖中,我們僅僅是概要的,采用以比較容易理解的方式描述了Web容器與Servlet之間的關(guān)系,以及當(dāng)接受到請求之后的處理流程。在實際的Web容器中,會比這要復(fù)雜很多。
【編輯推薦】