官术网_书友最值得收藏!

  • 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部署配置文件中的信息為準。

主站蜘蛛池模板: 西林县| 淮阳县| 康马县| 扎囊县| 丰县| 巩义市| 客服| 苏尼特左旗| 阿拉尔市| 汉川市| 连平县| 双牌县| 兴国县| 泉州市| 磴口县| 嵩明县| 通榆县| 绥阳县| 武宣县| 太湖县| 三门峡市| 张家港市| 鸡东县| 新河县| 长宁县| 土默特左旗| 荥阳市| 涿鹿县| 蓬安县| 齐齐哈尔市| 东丰县| 南安市| 浦县| 宁海县| 衡山县| 柯坪县| 库伦旗| 乳山市| 潼南县| 思茅市| 嘉兴市|