之前在開源中國看到一篇文章《初學 Java Web 開發,請遠離各種架構,從 Servlet 開發》,覺得很不錯。想到自己之前一直對各種架構執迷不悟,頓感慚愧。於是,看了孫鑫的《Servlet/JSP深入詳解:基於Tomcat的Web開發》、林信良的《JSP&Servlet學習筆記(第二版)》以及網上其他一些相關的資料,將自己的理解整理如下。
Web技術
隨著互連網技術的發展,基於HTTP和HTML的web應用急速增長。早期的web應用主要用於瀏覽新聞等靜態頁面,使用者通過HTTP協議請求伺服器上的靜態頁面,伺服器上的web伺服器軟體接收到請求後,讀取URI標示的資源,再加上訊息前序發送給用戶端瀏覽器,瀏覽器負責解析HTML,將結果呈現出來。
然而隨著時間發展,使用者已經不滿足於僅瀏覽靜態頁面。使用者需要一些互動操作,擷取一些動態結果。如果基於HTTP協議實現伺服器端軟體增強功能太過複雜,所以需要一些擴充機制來實現使用者想要的功能。早期使用的Web伺服器擴充機制是CGI(Common Gateway Interface,公用網關介面)。使用這種方法,使用者單擊某個連結或輸入網址來訪問CGI程式,web伺服器收到請求後,運行該CGI程式,對使用者請求進行處理,緊接著將處理結果併產生一個響應,該響應被返回給web伺服器,web伺服器對響應進行封裝,以HTTP響應的方式返回給瀏覽器。
CGI程式在一定程度上解決了使用者需求。不過還存在一些不足之處,如CGI程式編寫困難,回應時間較長,以進程方式運行導致效能受限。於是1997年,sun公司推出了Servlet技術,作為java陣營的CGI解決方案。
servlet與servlet容器
Java Servlet(Java伺服器小程式)是一個基於Java技術的Web組件,運行在伺服器端,它由Servlet容器所管理,用於產生動態內容。Servlet是平台獨立的Java類,編寫一個Servlet,實際上就是按照Servlet規範編寫一個Java類。Servlet被編譯為平台獨立的位元組碼,可以被動態地載入到支援Java技術的Web伺服器中運行。
Servlet容器也叫做Servlet引擎,是Web伺服器或應用程式伺服器的一部分,用於在發送的請求和響應之上提供網路服務,解碼基於MIME的請求,格式化基於MIME的響應。Servlet沒有main方法,不能獨立運行,它必須被部署到Servlet容器中,由容器來執行個體化和調用Servlet的方法(如doGet()和doPost()),Servlet容器在Servlet的生命週期內包容和管理Servlet。在JSP技術推出後,管理和運行Servlet/JSP的容器也稱為Web容器。
(註:常用的MIME類型:text/html,application/pdf,video/quicktime,application/java,image/jpeg,application/jar,application/octet-stream,application/x-zip)
有了servlet之後,使用者通過單擊某個連結或者直接在瀏覽器的地址欄中輸入URL來訪問Servlet,Web伺服器接收到該請求後,並不是將請求直接交給Servlet,而是交給Servlet容器。Servlet容器執行個體化Servlet,調用Servlet的一個特定方法對請求進行處理,併產生一個響應。這個響應由Servlet容器返回給Web伺服器,Web伺服器封裝這個響應,以HTTP響應的形式發送給Web瀏覽器。
servlet容器能提供什嗎?
我們知道需要由servlet容器來管理和運行servlet,但是為什麼要這樣做呢?使用servlet容器的原因有:
通訊支援:利用容器提供的方法,你能輕鬆的讓servlet與web伺服器對話,而不用自己建立serversocket、監聽某個連接埠、建立流等等。容器知道自己與web伺服器之間的協議,所以你的servlet不用擔心web伺服器(如Apache)和你自己的web代碼之間的API,只需要考慮如何在servlet中實現商務邏輯(如處理一個訂單)。
生命週期管理:servlet容器控制著servlet的生與死,它負責載入類、執行個體化和初始化servlet,調用servlet方法,以及使servlet執行個體被記憶體回收,有了servlet容器,你不需要太多的考慮資源管理。
多線程支援:容器會自動為它所接收的每個servlet請求建立一個新的java線程。針對使用者的請求,如果servlet已經運行完相應的http服務方法,這個線程就會結束。這並不是說你不需要考慮執行緒安全性,其實你還會遇到同步問題,不過這樣能使你少做很多工作。
聲明方式實現安全:利用servlet容器,你可以使用xml部署描述檔案來配置和修改安全性,而不必將其寫入程式碼寫到servlet類代碼中。
JSP支援:servlet容器負責將jsp代碼翻譯為真正的java代碼。
用與CGI程式相比,Servlet具有以下優點:
Servlet是單一實例多線程的運行方式,每個請求在一個獨立的線程中運行,而提供服務的Servlet執行個體只有一個。
Servlet具有可升級性,能響應更多的請求,因為Servlet容器使用一個線程而不是作業系統進程,而線程僅佔用有限的系統資源。
Servlet使用標準的API,被更多的Web伺服器所支援。
Servlet使用Java語言編寫,因此擁有Java程式語言的所有優點,包括容易開發和平台獨立性。
Servlet可以訪問Java平台豐富的類庫,使得各種應用的開發更為容易。
Servlet容器給Servlet提供額外的功能,如錯誤處理和安全。
Servlet容器的分類
根據Servlet容器工作模式的不同,可以將Servlet容器分為以下三類:
1)獨立的Servlet容器
當我們使用基於Java技術的Web伺服器時,Servlet容器作為構成Web伺服器的一部分而存在。然而大多數的Web伺服器並非基於Java,因此,就有了下面兩種Servlet容器的工作模式。
2)進程內的Servlet容器
Servlet容器由Web伺服器外掛程式和Java容器兩部分的實現組成。Web伺服器外掛程式在某個Web伺服器內部地址空間中開啟一個JVM(Java虛擬機器),使得Java容器可以在此JVM中載入並運行Servlet。如有用戶端調用Servlet的請求到來,外掛程式取得對此請求的控制並將它傳遞(使用JNI技術)給Java容器,然後由Java容器將此請求交由Servlet進行處理。進程內的Servlet容器對於單進程、多線程的伺服器非常適合,提供了較高的運行速度,但伸縮性有所不足。
3)進程外的Servlet容器
Servlet容器運行於Web伺服器之外的地址空間,它也是由Web伺服器外掛程式和Java容器兩部分的實現組成的。Web伺服器外掛程式和Java容器(在外部JVM中運行)使用IPC機制(通常是TCP/IP)進行通訊。當一個調用Servlet的請求到達時,外掛程式取得對此請求的控制並將其傳遞(使用IPC機制)給Java容器。進程外Servlet容器對客戶請求的響應速度不如進程內的Servlet容器,但進程外容器具有更好的伸縮性和穩定性。
Tomcat
學習Servlet技術,就需要有一個Servlet運行環境,也就是需要有一個Servlet容器,本文用的是Tomcat。
Tomcat是一個免費的開放原始碼的Servlet容器,它是Apache軟體基金會(Apache Software Foundation)的一個頂級項目,由Apache、Sun和其他一些公司及個人共同開發而成。由於有了Sun的參與和支援,最新的Servlet和JSP規範總是能在Tomcat中得到體現,Tomcat 6支援最新的Servlet 2.5和JSP 2.1規範。因為Tomcat技術先進、效能穩定,而且免費,因而深受Java愛好者的喜愛,並得到了部分軟體開發商的認可,成為目前比較流行的Web伺服器。
Tomcat和IIS、Apache等Web伺服器一樣,具有處理HTML頁面的功能,另外它還是一個Servlet和JSP容器,獨立的Servlet容器是Tomcat的預設模式。不過,Tomcat處理靜態HTML的能力不如Apache,我們可以將Apache和Tomcat整合在一起使用,Apache作為HTTP Web伺服器,Tomcat作為Web容器。
Tomcat伺服器接受客戶請求並做出響應的過程如下:
1)用戶端(通常都是瀏覽器)訪問Web伺服器,發送HTTP請求。
2)Web伺服器接收到請求後,傳遞給Servlet容器。
3)Servlet容器載入Servlet,產生Servlet執行個體後,向其傳遞表示請求和響應的對象。
4)Servlet執行個體使用請求對象得到用戶端的請求資訊,然後進行相應的處理。
5)Servlet執行個體將處理結果通過響應對象發送回用戶端,容器負責確保響應正確送出,同時將控制返回給Web伺服器。
Tomcat的安裝與配置
安裝Tomcat之前要先安裝JDK。JDK的下載與配置網上教程很多,可百度或Google。要下載Tomcat,首先訪問Tomcat項目的網址:http://tomcat.apache.org/,選擇要下載的Tomcat版本。
對於Windows作業系統,Tomcat提供了可執行檔安裝程式的下載,即“Windows Service Installer”連結。通過安裝程式安裝Tomcat,將把Tomcat安裝為Windows的服務。不過建議下載zip壓縮包,通過解壓縮的方式來安裝Tomcat,因為解壓縮的方式也適用於其他的作業系統(如Linux系統),並且更容易與其他的開發環境整合。對於初學者來說,也能更好地學習Tomcat的啟動過程。
下載完成後,使用WinZip或WinRAR等解壓縮工具將壓縮包解壓縮到指定的目錄中。然後在PATH環境變數中添加Tomcat的檔案夾下bin檔案夾的目錄,如D:\apache-tomcat-版本\bin即可。本文使用的是截止本文撰寫時的最新版本apache-tomcat-7.0.33。
Tomcat的目錄結構
Tomcat安裝後的目錄階層1所示。
圖1 Tomcat 7.0.33目錄階層各目錄的用途如表1所示。
目 錄 |
用 途 |
/bin |
存放啟動和關閉Tomcat的指令檔 |
/conf |
存放Tomcat伺服器的各種設定檔,其中包括server.xml(Tomcat的主要設定檔)、tomcat-users.xml和web.xml等設定檔 |
/lib |
存放Tomcat伺服器和所有Web應用程式需要訪問的JAR檔案 |
/logs |
存放Tomcat的記錄檔 |
/temp |
存放Tomcat運行時產生的臨時檔案 |
/webapps |
當發布Web應用程式時,通常把Web應用程式的目錄及檔案放到這個目錄下 |
/work |
Tomcat將JSP產生的Servlet源檔案和位元組碼檔案放到這個目錄下 |
表1 Tomcat的目錄結構及其用途
從表1中可以看到,lib目錄下存放的JAR檔案可以被所有的Web應用程式所訪問,如果多個Web應用程式需要訪問相同的JAR檔案,那麼可以將這些JAR檔案放到Tomcat的lib目錄下。此外,對於後面將要介紹的Java Web應用程式,在它的WEB-INF目錄下,也可以建立lib子目錄,在lib子目錄下可以存放各種JAR檔案,這些JAR檔案只能被當前Web應用程式所訪問。
運行Tomcat
在Tomcat安裝目錄下的bin子目錄中,有一些批次檔(以.bat作為尾碼名的檔案),其中的startup.bat就是啟動Tomcat的指令檔,用滑鼠雙擊這個檔案,如果你之前已經配置好了JDK和Tomcat(配置見圖2中PATH變數和JAVA_HOME變數),則會開啟3所示視窗。
圖2 JDK和Tomcat配置
圖3 Tomcat啟動視窗
註:如果未出現3所示的啟動視窗,而是一閃而過,則證明JDK和Tomcat未配置好,重新設定好即可。
開啟瀏覽器,在地址欄中輸入http://localhost:8080/(localhost表示本地機器,8080是Tomcat預設監聽的連接埠號碼),將出現4所示的Tomcat頁面。如果要關閉Tomcat伺服器,可以用滑鼠雙擊Tomcat bin目錄下的shutdown.bat檔案。
圖4 Tomcat預設首頁
Tomcat啟動分析
我們用文字編輯器開啟用於啟動Tomcat的批次檔startup.bat,對其做分析。具體分析過程見圖5。
圖5 startup.bat檔案分析
從圖5的分析中我們可以看見,startup.bat指令碼主要是查看當前命令所在目錄。看是否在tomcat\或tomcat\bin\目錄下。以及查看將調用該命令的參數傳遞給catalina.bat。最後調用catalina.bat start命令。startup.bat的主要作用是調用catalina.bat start命令。所以,在其他目錄下想同樣使用startup來啟動Tomcat,則需設定CATALINA_HOME環境變數。將CATALINA_HOME環境變數的值設定為Tomcat的安裝目錄即可。
可能有人會奇怪為什麼JAVA_HOME表示Java安裝目錄,而Tomcat安裝目錄卻不用TOMCAT_HOME來表示,卻要用CATALINA_HOME來表示。其實在Tomcat 4以前,就是使用TOMCAT_HOME來表示Tomcat安裝目錄的。
解了startup.bat檔案以後,我們再來看看真正負責啟動Tomcat伺服器的catalina.bat檔案。catalina.bat檔案比較長,所以具體分析過程見圖6。
圖6 catalina.bat檔案分析
由分析可知,catalina.bat實際上就是調用java命令運行Bootstrap類。從上面代碼可知tomcat確實是一個純java的程式,所有指令碼最後都變成直接使用java命令執行程式,與我們普通寫的java程式,沒有什麼不同。只不過由於 tomcat模式太多,需要各種參數(如debug,start等),所以需要使用指令碼來執行。另外,通過分析catalina.bat檔案,我們發現它還調用了一個檔案setclasspath.bat。在setclasspath.bat檔案中,它檢查JAVA_HOME環境變數是否存在,並通過JAVA_HOME環境變數,找到java.exe,用於啟動Tomcat。在這個檔案中,還設定了其他的一些變數,代表調用Java的標準命令,有興趣的話可以自己分析一下該檔案。
Tomcat的體繫結構
Tomcat伺服器是由一系列可配置的組件構成的,其中核心組件是Catalina Servlet容器,它是所有其他Tomcat組件的頂層容器。我們可以通過查看Tomcat安裝資料夾下的conf檔案夾中的server.xml檔案來瞭解Tomcat各組件之間的層次關係。由於server.xml注釋太多,特簡化如下:
<?xml version='1.0' encoding='utf-8'?><Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/><Engine name="Catalina" defaultHost="localhost"><Host name="localhost"><Context path="" docBase="WORKDIR" reloadable="true"/></Host></Engine></Service></Server>
其中WORKDIR為你想要匯入的項目路徑。我們下面簡單介紹一下各組件在Tomcat伺服器中的作用。
(1)Server
Server表示整個的Catalina Servlet容器。Tomcat提供了Server介面的一個預設實現,這通常不需要使用者自己去實現。在Server容器中,可以包含一個或多個Service組件。
(2)Service
Service是存活在Server內部的中間組件,它將一個或多個連接器(Connector)組件綁定到一個單獨的引擎(Engine)上。在Server中,可以包含一個或多個Service組件。Service也很少由使用者定製,Tomcat提供了Service介面的預設實現,而這種實現既簡單又能滿足應用。
(3)Connector
連接器(Connector)處理與用戶端的通訊,它負責接收客戶請求,以及向客戶返迴響應結果。在Tomcat中,有多個連接器可以使用。
(4)Engine
在Tomcat中,每個Service只能包含一個Servlet引擎(Engine)。引擎表示一個特定的Service的請求處理流水線。作為一個Service可以有多個連接器,引擎從連接器接收和處理所有的請求,將響應返回給適合的連接器,通過連接器傳輸給使用者。使用者允許通過實現Engine介面提供自訂的引擎,但通常不需要這麼做。
(5)Host
Host表示一個虛擬機器主機,一個引擎可以包含多個Host。使用者通常不需要建立自訂的Host,因為Tomcat給出的Host介面的實現(類StandardHost)提供了重要的附加功能。
(6)Context
一個Context表示了一個Web應用程式,運行在特定的虛擬機器主機中。什麼是Web應用程式呢?在Sun公司發布的Java Servlet規範中,對Web應用程式做出了如下的定義:“一個Web應用程式是由一組Servlet、HTML頁面、類,以及其他的資源群組成的運行在Web伺服器上的完整的應用程式。它可以在多個供應商提供的實現了Servlet規範的Web容器中運行”。一個Host可以包含多個Context(代表Web應用程式),每一個Context都有一個唯一的路徑。使用者通常不需要建立自訂的Context,因為Tomcat給出的Context介面的實現(類StandardContext)提供了重要的附加功能。
有關server.xml各部分的具體資訊會在另一篇文章中論述。Tomcat各組件的工作流程7所示。
圖7 Tomcat各組件的工作流程圖
Tomcat的管理程式
Tomcat提供了一個管理程式:manager,用於管理部署到Tomcat伺服器中的Web應用程式。manager Web應用程式套件組合含在Tomcat的安裝包中。要訪問manager Web應用程式,需要添加具有管理員權限的帳號,編輯%CATALINA_HOME%\conf\tomcat-users.xml檔案,在<tomcat-users>元素中添加manager角色,以及屬於該角色的使用者名稱和密碼,如下所示。
<?xml version='1.0' encoding='utf-8'?><tomcat-users> <role rolename="manager-gui"/> <user username="tomcat" password="tomcat" roles="manager-gui"/></tomcat-users>
註:使用者名稱和密碼可以自己設定,但角色名稱只能是manager-gui,不是一些資料提及的manager。
啟動Tomcat伺服器,開啟瀏覽器,在地址欄中輸入:http://localhost:8080/,將出現14所示的頁面。單擊“Manager App”連結,訪問manager Web應用,將看到8所示的登入介面。
圖8 Tomcat管理員登入介面
輸入使用者名稱tomcat,密碼1234,單擊“確定”按鈕,你將看到9所示的頁面。
圖9 manager Web應用程式首頁面
在這個頁面中,你可以部署、啟動、停止、重新載入、卸載Web應用程式。
轉載請註明出處:http://blog.csdn.net/iAm333