Servlet&JSP的那些事兒(二)

來源:互聯網
上載者:User

我們在Servlet解析(一)討論了Servlet、Servlet容器以及一個Servlet容器-Tomcat(包括安裝與配置,目錄結構,運行,啟動分析,體繫結構和如何管理程式)。而本篇,我們繼續論述Servlet技術包括Servlet
UML 類圖結構,Servlet容器如何處理請求,如何尋找正確的servlet,為什麼要採用映射機制,一個簡單的Web程式執行個體以及Servlet介面。首先,我們介紹一下開發Servlet需要用到的主要介面和類,其UML類圖1所示。

圖1 Servlet API中主要的介面與類的UML類圖

Servlet容器處理請求的過程

在開始本文之前,讓我們複習並細化一下Servlet容器處理請求的過程。

1)使用者點擊一個連結,指向了一個servlet而不是一個靜態頁面。

2)容器“看出”這個請求是一個Servlet,所以它建立了兩個對象HttpServletRequest和HttpServletResponse。

3)容器根據請求中的URL找到正確的Servlet,為這個請求建立或分配一個線程,並把請求和響應對象傳遞給這個Servlet線程。

4)容器調用Servlet的service()方法。根據請求的不同類型,service()方法會調用doGet()或doPost()方法。這裡假設調用doGet()方法。

5)doGet()方法產生動態網頁面,並把這個頁面“塞到”響應對象裡,需要注意的是,容器還有響應對象的一個引用!

6)線程結束,容器把響應對象轉換為一個HTTP響應,並把它發回給客戶,然後刪除請求和響應對象。

Servlet為什麼可以成為Servlet?

我們可以通過對一個Servlet的代碼進行分析而得出結論。2所示。

圖2 一個簡單的Servlet實現代碼

Servlet容器如何尋找正確的Servlet?

我們剛討論Servlet容器處理請求的過程時曾經講到過,Servlet容器會尋找正確的Servlet,那麼它是如何尋找的呢?

其實,使用者請求的URL會以某種方法映射到伺服器上一個特定的Servlet。一個Servlet會有多個名字,,主要針對三個不同的對象。

1)對於使用者來說,他所知道的,是一個公用的URL名。使用者看到html中對應一個Servlet的URL,但並不知道這個Servlet名字如何映射到伺服器上的目錄和檔案。這個URL名只是一個虛擬名字,方便使用者使用。
2)對於部署人員來說,他們可以建立一個名字,這個名字只有他自己以及實際作業環境中的其他人知道。同樣的,這也是一個虛擬名字,只用於部署Servlet。這個內部名字不一定與使用者使用的公用URL名匹配,也不必與Servlet類的實際檔案和路徑名一樣。
3)對於開發人員來說,Servlet類有一個完整名字,其中包括類名和包名。Servlet類檔案有一個實際的路徑和檔案名稱,這取決於伺服器上包目錄結構所在的位置。

為什麼要採用映射機制?

想想看我們都可以採用什麼辦法讓Servlet容器尋找正確的Servlet?有一種辦法是把真實路徑名和檔案名稱寫入程式碼到所有使用該Servlet的JSP和其他HTML頁面中,但如果你重新組織了你的應用,這時候目錄改變了怎麼辦?而如果採用映射的方法,就會有很大的靈活性,如果改變了應用的目錄,那麼只需要在映射中修改即可。再說基於安全考慮,你總不希望使用者對你伺服器上的目錄了如指掌吧?所以通過映射機制,讓使用者訪問一個虛擬名字,這樣會提高安全性。

我們通過一個典型的MVC執行個體來瞭解一下整個Web開發機制好了。MVC指的是Model,View,Controller。即模型,視圖,控制器。MVC將商務邏輯從Servlet中抽取出來,放到一個模型中(即一個可重用的Java類)。模型是業務資料和方法的組合。視圖使用JSP,HTML等實現使用者和系統的互動。在MVC中,視圖負責表示。它從控制器得到模型的狀態(不是真實得到,控制器會把模型資料能找到的一個地方)。另外,視圖還要獲得使用者輸入,交給控制器。控制器從請求獲得使用者輸入,並明確這些輸入對模型有什麼影響,告訴模型自行更新,並且還要讓視圖(JSP)能得到新的模型狀態。模型用於存放實際的商務邏輯和狀態。它知道用什麼規則來得到和更新狀態。另外,模型還負責和資料庫通訊。

下面我們看看web應用的開發與部署環境,分別3和圖4所示。

圖3 Web應用的開發環境

圖4 Web應用的部署環境

一個簡單的Web應用程式

MyDemo是一個簡單的Web應用程式。主要功能是使用者選擇一個顏色的英文單詞,然後“專家”會給出一個對應的中文詞語。Servlet即控制器的代碼如下:

package com.shan.web;import com.shan.model.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;/** ** A simple Servlet Demo ** @author shan **/public class MyDemoServlet extends HttpServlet{public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {response.setContentType("text/html; charset=UTF-8");PrintWriter out= response.getWriter();String color = request.getParameter("color");out.println("You select color:" + color);Expert expert = new Expert();out.println(expert.getResult(color));out.println("<br/>Expert's result:" + expert.getResult(color));}}

模型代碼如下所示:

package com.shan.model;import java.util.*;public class Expert{private Map<String, String> results = new HashMap<String, String>();public Expert() {results.put("White","白色");results.put("Black","黑色");results.put("Blue","藍色");results.put("Red","紅色");results.put("Green","綠色");}public String getResult(String color) {return results.get(color);}public static void main(String[] args) {Expert expert = new Expert();System.out.println(expert.getResult("White"));}}

部署描述檔案(DD)如下所示:

<?xml version='1.0' encoding='utf-8'?><web-app xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  version="3.0"  metadata-complete="true">    <description>      My Demo.    </description><servlet><servlet-name>selectServlet</servlet-name><servlet-class>com.shan.web.MyDemoServlet</servlet-class></servlet><servlet-mapping><servlet-name>selectServlet</servlet-name><url-pattern>/SelectColor.do</url-pattern></servlet-mapping></web-app>

有關web.xml檔案的具體解釋圖5所示。

圖5 部署描述檔案(DD)

用作視圖的表單頁面的HTML源碼如下(我命名為form.html):

<html><head><title>Form</title></head><body><h1 align="center">Selection Page</h1><form align="center" method="post" action="SelectColor.do">Select color:<br/><select name="color" size="1"><option>White</options><option>Black</options><option>Blue</options><option>Red</options><option>Green</options></select><input type="submit" value="Submit"></form></body></html>

由於例子簡單,在此就不再放運行結果了。有興趣的話可以按照上面的所講的開發與部署工程,然後自己運行。運行時需要編譯servlet。可以win+r,輸入cmd,切換到工程所在目錄。輸入語句:

javac -d classes src\com\shan\model\Expert.java
javac -classpath D:\apache-tomcat-7.0.33\lib\servlet-api.jar;classes -d .\classes src\com\shan\web\MyDemoServlet.java

編譯完成之後,將classes檔案夾等檔案複製到圖4所示的位置,之後輸入startup啟動Tomcat(註:Tomcat的配置按照上篇所述配置即可)。在瀏覽器網址欄輸入:localhost:8080/MyDemo/form.html,選擇一個顏色,點確認即可得到結果。

好了,講完了這個簡單的例子。讓我們繼續看看伺服器的整個運行過程。

1)使用者(瀏覽器)請求得到form.html頁面2)容器獲得form.html頁面3)容器把這個頁面返回給瀏覽器,使用者在表單上回答問題4)瀏覽器把請求資料發送給容器5)容器根據URL找到正確的servlet,並把請求傳遞給這個servlet 6)serlvet調用Expert尋求協助7)Expert類返回一個回答,servlet將這個回答增加到請求對象8)servlet將請求轉寄給JSP9)JSP從請求對象得到回答10)JSP為容器產生一個頁面11)容器把這個頁面(最終結果)返回給使用者。

在本例中,容器尋找正確servlet的過程是這樣的:

1)form.html中給出了調用的方法是post,給出了action是SelectColor.do,所以使用者填寫了表單後,會產生以下URL:localhost:8080/MyDemo/SelectColor.do,其中SelectColor.do是邏輯資源名。
2)容器搜尋部署描述檔案,找到<url-pattern>與/SelectColor.do匹配的一個<servlet-mapping>
3)容器看到對應的這個<url-pattern>的servlet-name>是SelectServlet,但這不是實際的servlet類檔案的名字。SelectServlet只是一個servlet名,不是servlet類的名字。
4)容器尋找servlet-name>是SelectServlet的<servlet>標記。
5)根據<servlet>標記中的<servlet-class>,容器知道了由哪個servlet類負責處理這個請求,如果這個servlet類還沒有初始化,就會載入類,並初始化servlet。
6)容器開啟一個新的線程來處理這個請求,並把請求傳遞給線程(傳遞給servlet的service()方法,由於使用者發出了一個HTTP post請求,所以service()方法會調用servlet的doPost()方法,把請求和響應對象作為參數傳遞給它)。
7)service()方法結束,所以線程要麼撤銷,要麼返回到容器管理的一個線程池。請求和響應對象引用已經出了範圍,所以會被記憶體回收機制回收。容器把響應(通過web伺服器)發回給使用者。

Servlet介面

在Java中我們學過Java Applet即Java小應用程式,它運行在用戶端的瀏覽器中。在此,我們可以類比一下Java Applet與Java Servlet,比較其異同點加深我們對Java Servlet的理解。

兩者的共同點:

它們都不是獨立的應用程式,都沒有main()方法。
它們都不是由使用者或程式員直接調用,而是生存在容器中,由容器管理。Applet運行在瀏覽器中,Servlet運行在Servlet容器中。
它們都有生命週期,都包含了init()和destroy()方法。

兩者的不同點:

Java Applet具有圖形介面,運行在用戶端的瀏覽器中;Java Servlet沒有圖形介面,運行在伺服器端的Servlet容器中。
要編寫一個Java Applet,需要從java.applet.Applet類派生一個子類;和Java Applet類似,要編寫一個Java Servlet,需要實現javax.servlet.Servlet介面。

javax.servlet.Servlet介面介面定義了如下5個方法:

public void init(ServletConfig config) throws ServletExceptionpublic void service(ServletRequest req, ServletResponse res)throws ServletException, java.io.IOExceptionpublic void destroy()public ServletConfig getServletConfig()public java.lang.String getServletInfo()

下面介紹一下這5個方法的作用。

init():在Servlet執行個體化之後,Servlet容器會調用init()方法,來初始化該對象,主要是為了讓Servlet對象在處理客戶請求前可以完成一些初始化的工作,例如,建立資料庫的串連,擷取配置資訊等。對於每一個Servlet執行個體,init()方法只能被調用一次。init()方法有一個類型為ServletConfig的參數,Servlet容器通過這個參數向Servlet傳遞配置資訊。Servlet使用ServletConfig對象從Web應用程式的配置資訊中擷取以名-值對形式提供的初始化參數。另外,在Servlet中,還可以通過ServletConfig對象擷取描述Servlet運行環境的ServletContext對象,使用該對象,Servlet可以和它的Servlet容器進行通訊。

service():容器調用service()方法來處理用戶端的請求。要注意的是,在service()方法被容器調用之前,必須確保init()方法正確完成。容器會構造一個表示用戶端請求資訊的請求對象(類型為ServletRequest)和一個用於對用戶端進行響應的響應對象(類型為ServletResponse)作為參數傳遞給service()方法。在service()方法中,Servlet對象通過ServletRequest對象得到用戶端的相關資訊和請求資訊,在對請求進行處理後,調用ServletResponse對象的方法設定響應資訊。

destroy():當容器檢測到一個Servlet對象應該從服務中被移除的時候,容器會調用該對象的destroy()方法,以便讓Servlet對象可以釋放它所使用的資源,儲存資料到持久存放裝置中,例如,將記憶體中的資料儲存到資料庫中,關閉資料庫的串連等。當需要釋放記憶體或者容器關閉時,容器就會調用Servlet對象的destroy()方法。在Servlet容器調用destroy()方法前,如果還有其他的線程正在service()方法中執行,容器會等待這些線程執行完畢或等待伺服器設定的逾時值到達。一旦Servlet對象的destroy()方法被調用,容器不會再把其他的請求發送給該對象。如果需要該Servlet再次為用戶端服務,容器將會重新產生一個Servlet對象來處理用戶端的請求。在destroy()方法調用之後,容器會釋放這個Servlet對象,在隨後的時間內,該對象會被Java的垃圾收集器所回收。

getServletConfig():該方法返回容器調用init()方法時傳遞給Servlet對象的ServletConfig對象,ServletConfig對象包含了Servlet的初始化參數。

getServletInfo():返回一個String類型的字串,其中包括了關於Servlet的資訊,例如,作者、版本和著作權。該方法返回的應該是純文字字串,而不是任何類型的標記(HTML、XML等)。

每個請求都在一個單獨的執行個體中運行

由上文我們知道,在servlet執行個體建立之後,在servlet能為客戶請求提供服務之前,容器會在servlet執行個體上調用init()方法。如果你有初始化代碼,就應該覆蓋servlet類的init()方法,否則會調用GenericServlet的init()方法。而對應每個客戶請求(無論是誰,無論是不是同一個人,只針對請求),容器都會建立一對新的請求和響應對象,建立一個新的線程/棧。任何servlet類都不會有多個執行個體,除非一種特殊情況(SingleThreadModel,其實很糟糕),我們不討論這種特殊狀況。

轉載請註明出處:http://blog.csdn.net/iAm333

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.