從網絡的早期階段開始,人們就但願他們的網絡服務器不只可以顯示靜態文檔,通用網關接口(CGI) 擴展了服務器的能力,但其代價是增長了額外的處理進程。FastCGI則把外部CGI 處理進程同網絡服務器更緊密地集成在一塊兒,另外,對於專有的,諸如NSAPI 和ISAPI 這樣的服務器API,它們直接把外部進程以服務器插件的形式集成到服務器中。如今有了Java servlets,它們的功能強大,能夠快速替代你現有的CGI程序。html
什麼是servlets?java
就象applet擴充了網絡瀏覽器的能力同樣,servlets這個Java部件,擴充了網絡服務器的能力。對於任何種類的服務器端的處理,Servlets能夠做爲server-side includes使用或者做爲CGI程序(在JavaSoft的Java Web server中能夠做爲插件)執行。 Servlets能夠移植,不象CGI和專有的API模塊,你能夠利用Java的「編寫一次,處處運行」的機制,在你的企業中配置網絡應用程序。Servlets的運行也很穩固,在 servlet 中你建立了一個數據庫鏈接,下一次你訪問servlet時鏈接仍然存在,這同CGI 程序不同。Servlets也具備擴展性,因此你可使用面向對象的程序設計方法,來減小開發時間。Servlets能夠運行在任何支持servlet的網絡服務器上。目前,servlet SDK除了支持JavaSoft的Java Web server,還支持Netscape, Apache 和IIS,以及大量第三方的網絡服務器。數據庫
JSDK導遊數組
爲了建立servlets,你須要Java servlet SDK (JSDK),它能夠從JavaSoft網站下載。JSDK包含諸如javax.servlet,javax.servlet.http等包,其中包含有你本身建立servlets時所須要的類和接口。對於sun.servlet 包來講,其中包含了網絡服務器用來運行servlets所須要的類。 (對Servlet的支持一般是經過服務器插件的形式)。一旦你有了JSDK,你只要建立GenericServlet類的子類,而且重載若干方法。GenericServlet 定義了你應該重載的三種主要方法: init(), service()和destroy()。瀏覽器
init() :初始化你的servlet,諸如打開數據庫鏈接。緩存
destroy():在applet運行結束後,清除servlet 自身。服務器
service():每次調用servlet時,就調用service()方法。有兩個對象 ServletRequest和ServletResponse須要傳送給servlet,用於處理客戶請求。網絡
爲了幫助處理基於Web 的事務,JSDK 在 javax.servlet.http包中有個HttpServlet類。HttpServlet是從GenericServlet中派生出來的,它提供了service()的一個實現,該實現用於自動處理GET, HEAD和POST的請求。多線程
HttpServlet類中的方法有doGet()和doPost()。一個典型的CGI servlet只須要實現doGet()和doPost()方法。 doGet()和doPost()的參數爲HttpServletRequest和HttpServletResponse。app
HttpServletRequest是個接口,該接口提供了從客戶的請求獲取信息的一些方法。例如, getParameter()方法返回在客戶請求中的關鍵字/值對(或者從請求串中取得,或者從POSTed數據中取得)。
HttpServletResponse提供了輸出流,使得servlet把HTML格式的輸出返回給客戶。
基本Servlet代碼
代替你的CGI
下面爲一段能夠取代CGI程序的基本的servlet代碼。Servlet完成以下的簡單事情:列出由HTML表單蒐集的關鍵字/值對(key/value)。
BasicCGIServlet處理POST,也用一樣處理GET。因此doPost()和doGet()都調用doService()。doService()能夠在子類中重載,以實現更多特定的功能。
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class BasicCGIServlet extends HttpServlet {
public BasicCGIServlet () {
super();
}
public void doPost (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doService(req, resp);
}
public void doGet (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doService(req, resp);
}
protected synchronized void doService (HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
// get an output stream to write to
ServletOutputStream out = resp.getOutputStream();
// set the content type for the response
resp.setContentType (\\"text/html\\");
// optionally you should also set any special content-encoding
// and content length response headers, and return status codes
// write out the response!
out.println (\\"<body
bgcolor=\\\\"white\\\\">\\");
out.println (\\" \\");
out.println (\\"
\\");
for (Enumeration e = req.getParameterNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
out.println (\\"
\\");
}
out.println (\\"
Key | Value |
---|---|
\\" + key + \\" | \\" + req.getParameter(key) + \\" |
\\");
}
}
當調用req.getParameterNames()時,servlet請求對象讀入表單數據,而且把它解碼爲關鍵字/值對(事實上,一旦第一次調用getParameterNames(),或者getParameterValues(),或者getParameter()
時,就進行解碼)。 getParameterNames()返回全部關鍵字的列舉。getParameter()返回同特定關鍵字相對應的值。當servlet請求被解析成關鍵字/值對時,每一個關鍵字的值保存在String數組中,以即可以處理一個關鍵字有多個值的狀況。調用getParameterValues(),返回的是String數組,而調用 getParameter()後,則僅返回String數組中的第一個元素。
你也許會注意到doService()是個同步化的方法。這是由於servlets 一般是在多線程環境下運行的。由於網絡服務器建立的servlet對象只有一個實例,因此servlet必須可以對同時發生的請求提供服務。所以,Servlets須要確保:這些請求在訪問共享資源時保持同步。這些共享資源包括實例變量,數據庫鏈接和文件流等。
運行你的servlet
一旦編寫好servlet,而且編譯成功以後,你能夠把它放到網絡服務器中servlet別名目錄中。就同服務器中的cgi-bin別名目錄的做用同樣,任何放在servlet 目錄中的文件,一旦被做爲url的一部分被請求時,將被做爲servlets執行。例如,BasicCGIServlet能夠經過以下的url調用: http://mycompany.com/servlet/BasicCGIServlet。你既能夠直接調用該url (而且傳送給servlet一個請求關鍵字/值對的串),也能夠經過HTML表單中的一個動做來調用。要了解更多的支持servlet的網絡服務器的信息,請參閱JSDK中的有關文檔信息。
進一步的用法
GenericServlet和 HttpServlet提供了一個構建servlets的固定的基類。經過重載service()方法,你能夠在它們的基礎上進行構建。例如,你能夠加入對響應緩存的支持(請參見HttpServlet 中的getLastModified()),也能夠加入對HTTP 1.1方法的支持,等等。你甚至能夠構建一個擴展的模板引擎。(有誰真的喜歡在他們的程序中內置HTML代碼呢?)
另一個用法是對JSDK進行擴展,使之除了支持標準的application/x-www-form-urlencoded mime 類型以外,還支持其餘類型的表單編碼。例如,你能夠加入對multipart/form-data mime類型的支持,用於處理經過HTTP上載文件。接口方法getParameterNames(), getParameterValues()等等,都是在sun.servlet包中實現的,因此你須要配置JSDK ,以便加入這些支持。還有一種變通的方法,你能夠本身實現有關方法,但那樣作,就須要複製代碼或者改變JSDK的語義。上面的這些方法都是可行的,可是沒有哪種是天衣無縫的。
結論
如今你應該會本身建立Java servlets了,它們能夠用來代替傳統的Perl和C/C++ CGI程序。 Java的面向對象的特性和「編寫一次,處處運行」的機制使得Java servlets的編寫很簡單。Servlet的穩固性,能夠解決有關狀態管理問題,而這些都是隻用一次的CGI程序解決實際問題時一般會遇到的難題。 Servlets能夠利用Java語言的全部功能,包括JDBC和RMI。因爲大多數網絡服務器都加入了對servlet的支持,Java將迅速成爲開發企業級應用程序的一種可選語言。