- Java EE 程序設計
- 郝玉龍編著
- 3777字
- 2019-07-01 10:16:03
3.3 第一個Servlet
在了解了Servlet的基礎知識后,現在開始編寫第一個Servlet組件。
編寫響應HTTP請求的Servlet只需要兩步:
(1)創建一個擴展了javax.servlet.http.HttpServlet接口的類。javax.servlet.http.HttpServlet接口是javax.servlet.GenericServlet的擴展接口,它包含了分析HTTP請求Header和將客戶端信息打包到javax.servlet.http.HttpServletRequest類中的相關代碼。
(2)重寫Servlet組件的doGet或doPost方法實現對HTTP請求信息的動態響應。這些方法是Servlet實際完成工作的地方。HTTP 1.1支持七種請求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TRACE。GET和POST是Web應用程序中最常用的兩個方法。根據請求是通過GET還是POST發送,覆蓋doGet、doPost方法之一或全部。doGet和doPost方法都有兩個參數,分別為HttpServletRequest接口和HttpServletResponse接口。HttpServletRequest提供訪問有關客戶端請求信息的方法,包括表單數據、請求Header等。HttpServletResponse除了提供用于指定HTTP應答狀態(200、404等)、應答頭部信息(Content-Type、Set-Cookie等)的方法之外,最重要的是它提供了一個用于向客戶端發送數據的輸出流對象。這個輸出流對象可以是字節流或二進制數據流。對于Servlet開發來說,它的大部分工作是操作此輸出流并返回給客戶端。
提示:doGet和doPost這兩個方法是由service方法調用的,有時可能需要直接覆蓋service方法,例如Servlet要對GET和POST兩種請求采用同樣的處理方式。但不推薦那樣做。
Servlet也可以重寫init和destroy方法以實現Servlet定制化的初始化和析構。重寫init和destroy方法的典型場景是在init方法中建立數據庫連接并在destroy方法中斷開它。
下面開始創建Servlet。Servlet作為一個Web組件,必須包含在某個Web應用程序中,因此,首先創建Web應用程序Chapter3。
注:本章中所有的示例都包含在此Web應用程序中。
打開NetBeans開發環境,單擊“文件”菜單的“新建項目”選項,彈出如圖3-4所示的“新建項目”對話框。

圖3-4 創建Web應用項目Chapter3
在“類別”列表框中選中Java Web選項,在“項目”列表框中選中“Web應用程序”。單擊對話框底部的“下一步”按鈕,進入下一頁面,如圖3-5所示。

圖3-5 設置Web應用項目名稱和位置
在“項目名稱”文本框輸入Chapter3。單擊“項目位置”右側的“瀏覽”按鈕可選擇項目的位置。選中“設置為主項目”復選框將當前項目設置為主項目。單擊底部的“下一步”按鈕,進入下一頁面,如圖3-6所示。

圖3-6 設置Web應用服務器
Web應用程序必須發布到Java EE Web服務器上才能夠運行。在這里從“服務器”下拉列表框中選擇NetBeans內置的服務器“GlassFish Server 3.1.1”,默認其他選項設置,單擊“完成”按鈕,則Web應用程序創建完畢。
下面為Web應用創建一個Servlet。在“項目”視圖中選中Web應用程序Chapter3,右擊,在彈出的快捷菜單中選擇“新建”→Servlet命令,彈出如圖3-7所示對話框。

圖3-7 “新建Servlet”對話框
在“類名”文本框中輸入Servlet實現類的名稱First,在“包”文本框中輸入Servlet實現類所在的包名com.servlet,單擊“下一步”按鈕,進入下一頁面,如圖3-8所示。

圖3-8 配置Servlet部署信息
這一步主要完成Servlet組件的部署配置,主要工作是設置Servlet的名稱以及對應的URL模式名稱。所謂URL模式,就是代表客戶端請求的一個字符串,Web容器總是將匹配此字符串內容的請求轉發到此Servlet組件來處理以便返回動態響應。“Servlet名稱”文本框中的內容為Servlet的顯示名稱,并不要求等于前面定義的類名。在“Servlet名稱”文本框中輸入First。在“URL模式”文本框輸入Servlet所對應的請求URL模式“/First”。選中“將信息添加到部署描述符(web.xml)”復選框,單擊“完成”按鈕,則一個名為First的Servlet組件創建完畢。NetBeans將在編輯器中自動打開Servlet的源代碼。
在這個Servlet中,只要求Servlet在接收到請求后向客戶端返回“Hello, World!”的提示信息。完整代碼如程序3-1所示。
說明:為節省篇幅,代碼中的一些注釋信息被省略,完整的代碼請到清華大學出版社的網站下載。另外,有些注釋信息是NetBeans自動生成,由于機器環境的不同,讀者所生成的注釋信息可能與本書配套資源中的不完全一致,如create date、author信息等,這完全正常。
程序3-1:First.java
package com.servlet; import java.io.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; public class First extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet First</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World! </h1>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } public String getServletInfo() { return "Short description"; } }
程序說明:NetBeans自動生成了Servlet的框架代碼,其中方法doGet和doPost分別用來響應客戶端發出的GET和POST請求,開發人員可以分別編寫代碼覆蓋上述兩個方法以實現對GET和POST請求的處理,在這里它們都默認調用方法processRequest(),這是NetBeans推薦的一種編程實踐。方法processRequest有兩個輸入參數:request是代表客戶端發出的請求信息的HttpServletRequest接口對象;response是代表Servlet返回客戶端的響應的HttpServletResponse接口對象。在方法processRequest中,首先調用response方法setContentType("text/html; charset=UTF-8")設置響應返回類型為HTML文件,編碼類型為UTF-8,然后調用response的getWriter方法獲取響應對應的PrintWriter對象,最后利用PrintWriter對象的out方法在客戶端打印信息“Hello World!”。
注意:方法doGet、doPost的聲明中必須包含拋出兩個異常(ServletException、IOException)。
為訪問編寫的Servlet,必須將其打包并發布到Java EE服務器上,然后啟動服務器來訪問Servlet。在前面創建Web應用程序的時候已經設置Java EE Web服務器為NetBeans內置的服務器GlassFish Server 5。
在“項目”視圖中選中Web應用程序Chapter3,右擊,在彈出的快捷菜單中選擇“生成項目”命令,則Web應用被自動打包。
重新選中Web應用程序Chapter3,右擊,在彈出的快捷菜單中選擇“部署項目”命令,則Web應用被部署到Web服務器。再一次選中Web應用程序Chapter3,右擊,在彈出的快捷菜單中選擇“運行項目”命令,則Web服務器被啟動且Web應用被加載運行。
說明:在執行“運行項目”的操作時,如果Web服務器已經處于運行狀態,則服務器只執行加載Web應用的操作。
打開IE瀏覽器,在地址欄中輸入http://localhost:8080/Chapter3/First,程序運行結果如圖3-9所示。

圖3-9 Servlet運行結果頁面
讀到這里可能會產生疑問:Web服務器是如何將瀏覽器中輸入的地址http://localhost:8080/Chapter3/First自動映射到Servlet組件First的呢?
這個秘密在于:每個Web應用程序都對應一個稱為上下文信息的字符串,表示此Web應用所對應的URL請求地址。在“項目”視圖選中Web項目Chapter3,右擊,在彈出的快捷菜單中選中“屬性”命令,彈出如圖3-10所示對話框。在左側的“類別”欄目中選中“運行”,則在右側“上下文路徑”文本框中可查看并修改Web應用上下文信息。

圖3-10 查看Web應用上下文路徑
當Web應用程序部署到服務器上時,服務器根據此信息便知道將上下文信息為“/Chapter3”請求映射到此Web應用。
另外,為描述Web應用內部信息,每個Web應用還通常包含一個配置文件web.xml來對自身包含的Web組件的信息進行說明。Servlet添加到Web應用后,在Web應用的配置文件web.xml中包含Servlet及其URL映射信息。Java EE服務器正是根據web.xml中的配置信息將客戶端的請求轉發給Web應用中適當的Web組件。
web.xml的詳細內容如程序3-2所示,其中的<Servlet>節點指明Servlet名稱與Servlet實現類之間的對應關系。<Servlet-mapping >節點指明Servlet名稱與請求URL之間的對應關系。再回頭看在瀏覽器地址欄中輸入的請求地址。地址最前面的部分“http://localhost:8080”將請求導向本機安裝的Java EE服務器GlassFish Server 5。其中localhost代表本機,8080代表Java EE服務器程序的端口號。那么對于請求地址剩余信息的解析就由Java EE服務器來接管。Java EE服務器根據請求地址中的“/Chapter3”和服務器上Web應用的上下文信息確定請求由Web應用Chapter3處理響應。Java EE服務器在Chapter3 Web應用的配置文件web.xml中查找請求地址中的“/First”對應的Servlet映射信息,最終確定請求由名為First的Servlet處理響應,此Servlet對應的類文件就是剛才編寫的com.servlet.First。
程序3-2:web.xml
<? xml version="1.0" encoding="UTF-8"? > <web-app version="3.0" 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"> <servlet> <servlet-name>First</servlet-name> <servlet-class>com.servlet.First</servlet-class> </servlet> <servlet-mapping> <servlet-name>First</servlet-name> <url-pattern>/First</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app>
web.xml對于一個Web應用是如此的重要,因此在這里不得不對它多說幾句。web.xml的作用就是作為Web容器與Web應用交互的場所,它一定位于應用的WEB-INF子目錄下。它包含了Web應用的重要的描述信息,以本例來說,<servlet>節點用來指明Servlet邏輯名稱與Java實現類之間的對應關系;<servlet-mapping>用來指明Servlet邏輯名稱與URL模式之間的對應關系。當然還有其他節點用來描述Web應用其他方面的信息,詳細信息可以查閱DTD(Document Type Definitions,文檔類型定義)文檔。Web容器正是根據web.xml文件描述的信息來操作Web應用的。
可以將程序3-2中的代碼片段:
<servlet-mapping> <servlet-name>First</servlet-name> <url-pattern>/First</url-pattern> </servlet-mapping>
改為
<servlet-mapping> <servlet-name>First</servlet-name> <url-pattern>/FirstServlet</url-pattern> </servlet-mapping>
將程序3-2保存,重新發布Web應用并啟動瀏覽器,在地址欄中輸入http://localhost:8080/Chapter3/First,則將得到如圖3-11所示的運行結果頁面。

圖3-11 修改Web應用配置后的運行結果
404錯誤代碼表示文件無法定位的錯誤類型。產生錯誤的原因在于此時Servlet組件First對應的請求URL不再是“/First”,而是“/FirstServlet”。在地址欄中輸入http://localhost:8080/Chapter3/FirstServlet,看看又會得到什么運行結果頁面。
值得一提的是,自Java EE 5規范以后,推薦使用注解來代替編寫復雜的配置文件。下面修改程序3-1,代碼如程序3-3所示。
注:為節省篇幅,書中代碼主要顯示編程實踐中的重點內容,完整代碼請參考本書的源代碼包。
程序3-3:First.java
package com.servlet; … @WebServlet(name="First", urlPatterns={"/First"}) public class First extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet First</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World! </h1>"); out.println("</body>"); out.println("</html>"); out.close(); } finally { out.close(); } } … }
程序說明:與程序3-1相比,在類的定義前添加了一個注解@WebServlet,它包含兩個屬性name和urlPatterns,分別用來定義Servlet組件的名稱和URL模式。當部署此組件時,Web容器將根據此注解自動完成對此Servlet組件的配置。還要注意的是,因為使用了注解@WebServlet,因此要在代碼中添加對javax.servlet.annotation.WebServlet的引用。
在“項目”視圖的“配置文件”目錄下刪除掉web.xml,重新發布應用,打開瀏覽器重新輸入請求地址http://localhost:8080/Chapter3/First,看看會不會得到如圖3-9所示的運行結果。
說明:由于新的Java EE規范推薦采用注解的方式,因此在以后的示例中,本書將盡可能采用注解的方式來部署Web組件。但配置文件web.xml在有些情況下還是必需的,如設置Web應用的安全屬性等,因此,注解并不能完全取代web.xml,它只是使得web.xml更加簡潔。
如果Web組件中既采用了注解來配置組件,在配置文件web.xml中又包含了此組件配置信息,那么Web容器在進行URL解析映射時該如何進行呢?下面還是親自動手實驗一下吧。
在“項目”視圖的“配置文件”目錄下重新添加配置文件web.xml,內容如程序3-4所示。
程序3-4:web.xml
<? 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"> <servlet> <servlet-name>First</servlet-name> <servlet-class>com.servlet.First</servlet-class> </servlet> <servlet-mapping> <servlet-name>First</servlet-name> <url-pattern>/FirstServlet</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app>
程序說明:注意在程序3-4中servlet對應的URL模式(/FirstServlet)與程序3-3中注解@WebServlet對應的URL模式(/First)是不一致的。重新發布Web應用,在瀏覽器的地址欄輸入http://localhost:8080/Chapter3/FirstServlet,將得到如圖3-9所示的運行界面,而在瀏覽器的地址欄輸入http://localhost:8080/Chapter3/First卻得到一個錯誤提示信息。這就證明,在Web部署配置文件和注解都對Servlet進行配置的情形下,Web容器將以Web部署配置文件中的信息為準。
- 零基礎學Visual C++第3版
- 算法基礎:打開程序設計之門
- jQuery從入門到精通 (軟件開發視頻大講堂)
- Raspberry Pi 2 Server Essentials
- ASP.NET 3.5程序設計與項目實踐
- Python數據結構與算法(視頻教學版)
- Python深度學習原理、算法與案例
- Building Microservices with .NET Core
- Android嵌入式系統程序開發:基于Cortex-A8(第2版)
- WCF技術剖析(卷1)
- 原型設計:打造成功產品的實用方法及實踐
- 3ds Max 2018從入門到精通
- Android嵌入式系統程序開發(基于Cortex-A8)
- 優化驅動的設計方法
- Spring Boot 2+Thymeleaf企業應用實戰