Java Servlet 程式設計初步

作者:蔡煥麟
日期:Jan-17-2003
更新:Dec-20-2003 


1.0 簡介

這份文件是給初次嘗試撰寫 Java servlet 的人看的,內容包括:

  1. 開發環境設定,包括安裝 JDK 及 Tomcat。
  2. 撰寫一支簡單的 servlet 程式。
  3. 將 servlet 部署到 Tomcat 環境。

2.0 準備你的開發環境

2.1 安裝 Java 2 SDK

  1. http://java.sun.com/ 下載最新版的 J2SE SDK。
  2. 將 JDK 安裝至目錄 c:\j2sdk\。
  3. 安裝完後,需設定環境變數。在桌面上的〔我的電腦〕圖示上點一下滑鼠右鍵,選〔內容〕,切到〔進階〕頁夾,按一下〔環境變數〕鈕,新增一個系統環境變數,變數名稱為 "JAVA_HOME"(不包含引號),值為 "c:\j2sdk",參考圖 1。接著在系統環境變數 "PATH" 中加入 "c:\j2sdk\bin"(做法是先選擇系統環境變數 "PATH",然後按〔編輯〕鈕,PATH 中各個路徑是以分號 ';' 隔開)。後面以 %JAVA_HOME% 代表此 Java 的安裝目錄。

圖一

:如果你修改了環境變數之後,發現好像沒有作用,可以嘗試重新開機看看。此動作並非必要,只是某些應用程式必須結束後重新開啟才會讀取到新的環境變數(例如: Total Commander),如果你發現新的環境變數沒有生效,又不知道應該重新執行哪些應用程式,重新開機就是最簡單的方式。

2.2 安裝 Tomcat 5

  1. http://jakarta.apache.org/ 下載 Tomcat 安裝程式(下載附檔名是 .exe 的檔案)。
  2. 將 Tomcat 安裝至目錄 "c:\Tomcat"。如果你希望每次開機就自動啟動 Tomcat 服務,在安裝過程中要將 "Service" 項目打勾,參考圖 2。


    圖 2
  3. 安裝完成後,增加一個系統環境變數 "CATALINA_HOME",值為 "c:\tomcat"。
  4. 現在 Tomcat 服務應該已經自動啟動了,開啟瀏覽器,並且輸入 URL "http://127.0.0.1:8080"(http 一定要輸入),如果安裝無誤,應會看到如圖 3 的畫面。

圖 3

在安裝步驟的第 2 步,如果不將 NT service 項目打勾的話,每次要啟動 Tomcat 伺服器時必須執行 Tomcat 的 bin 目錄下的 start.bat,而且啟動之後會開啟一個 DOS 視窗,若將此 DOS 視窗關閉,Tomcat 伺服器也就隨之關閉了。

關於 Tomcat 的安裝與設定,[2] 有更詳細的說明。

2.3 設定 CLASSPATH 環境變數

編譯 serlvet 程式時必須讓 javac 編譯器找得到 HttpServlet 和相關的類別,有兩種方法:

兩種方法都可以。

3.0 撰寫 Servlet

開啟文字編輯器(建議使用 UltraEdit),輸入下列程式碼,並且存檔成 HelloServlet.java(請自己輸入,勿用剪貼的,並注意大小寫)。

// Filename: HelloServlet.java
// Compile: javac HelloServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
        // 下面兩行讓中文字能正確顯示
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();
        out.println("<HTML>");
        out.println("<BODY>");
        out.println("<p>Hello! 這是我的第一支 Java servlet 程式。</p>");
        out.println("</BODY>");
        out.println("</HTML>");
  }
}

存檔完後,編譯 HelloServlet.java,在 DOS 視窗下輸入命令:

javac HelloServlet.java

若編譯無誤,會產生一個 HelloServlet.class 檔案。請參考相關書籍以了解程式碼結構以及相關細節。

若編譯時出現錯誤,錯誤訊息中包含字串 "package javax.servlet.http does not exist",表示 Java 編譯器找不到 javax.servlet.http 這個 package,請回到步驟 2.3 檢查看看哪裡出問題了。

4.0 佈署

Tomcat 安裝完成後,已經有一些編譯好的 servlet 範例可以執行,這些範例都在 "c:\Tomcat\webapps\examples\" 目錄以下,但我們希望自己的程式佈署在獨立的目錄下,假設我們希望自己寫的 servlet 都放在 myapp 目錄下,請按下列步驟進行佈署:

  1. 建立以下目錄結構:"c:\Tomcat\webapps\myapp\WEB-INF\classes\"。請注意大小寫是有區別的。
  2. 把之前編譯後產生的 HelloServlet.class 複製到 "c:\Tomcat\webapps\myapp\WEB-INF\classes\" 目錄下。
  3. 開啟文字編輯器,將下列文字輸入(剪貼亦可)並存檔,檔名為 "c:\Tomcat\webapps\myapp\WEB-INF\web.xml"。

    表 1
    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
        <servlet>
          <servlet-name>
              HelloServlet
          </servlet-name>
          <servlet-class>
              HelloServlet
          </servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/HelloServlet</url-pattern>
        </servlet-mapping>
    </web-app>

    其中 <servlet-mapping> 標籤可以將網址和實際執行的 servlet 路徑做轉換對應,請特別注意 <url-pattern> 這個標籤的內容是 "/HelloServlet",前面的斜線是必要的,這個標籤值代表使用者在瀏覽器上輸入的網址的一部分,當使用者輸入的網址符合這個 URL 樣式時,就會轉而呼叫你指定的 servelt,也就是 HelloServlet。因為此 servlet 範例程式的根目錄是 "myapp",所以加上 "/HelloServlet" 之後,瀏覽的網址就是 "http://127.0.0.1:8080/myapp/HelloServlet"。這部分你可以參考 [1] 的 2.4 節的說明。

  4. 開啟瀏覽器,在網址列輸入 URL "http://127.0.0.1:8080/myapp/HelloServlet",如果可以看到如圖 4 的畫面,就表示成功了。如果發生錯誤,請重頭檢查每一個步驟,看看哪裡出問題了,例如:Tomcat 服務是否已經啟動了,環境變數是否設定正確,大小寫是否都輸入正確....等。

圖 4

以上的步驟主要是先建立子目錄,複製檔案,然後再編輯 web.xml 讓 tomcat 可以根據網址找到對應的 servlet 檔案。許多書籍和文件都是教你修改 "c:\tomcat\conf\server.xml",在其中加入一個 <context> 標籤並設定相關路徑,這種方法我目前還沒試成功過,如果你有興趣的話也可以嘗試看看,但並不建議你去改 server.xml,因為這是 Tomcat 專屬的設定方式,若程式有一天要佈署到別的 Web 伺服器,還要費工夫重新設定,而 web.xml 則是通用的方式。

第一個範例成功後,如果你還不太了解程式碼的每個細節,請到相關書籍中尋找線索,了解每個環節,並且試著動手修改一些程式碼,重新佈署,看看修改後的結果。

每當你修改 servlet 程式,重新編譯及佈署之後,Tomcat 不會自動偵測到並重新載入新的 servlet class,解決方法請參閱 6.1 節的說明。

5.0 練習撰寫其他範例

如果這個範例已經沒有問題,你可以試著練習寫一個網頁,可以讓使用者輸入名稱,並且有一個〔送出查詢〕按鈕,如圖 5:

圖 5

網頁的原始碼如表 2:

表 2. Hello.htm

<html>
<body>
    <form method=get action="/myapp/Hello">
    請輸入姓名:
    <input type=text name="UserID"><p>
    <input type=submit>
    </form>
</body>
</html>

如果使用者在姓名欄輸入 "殘劍飛雪",然後按下〔送出查詢〕鈕,該查詢請求會傳送到你的 servlet 程式,你的程式則會傳回如圖 6 的畫面(注意網址列的內容):

圖 6

Servlet 的原始碼列在表 3。

表 3. Hello.class

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Hello extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 下面兩行讓中文字能正確顯示
        response.setContentType("text/html; charset=big5");
        request.setCharacterEncoding("big5");

        PrintWriter out = response.getWriter();

        String UserID = request.getParameter("UserID");
        out.println("<html><body>");
        out.println("您好, " + UserID);
        out.println("</body></html>");
    }

    public String getServletInfo() {
        return "A servlet that knows the user ID";
    }
}  

編譯之後的檔案可以跟第一個範例佈署到同一個目錄下,但 web.xml 要加入下列內容:

    <servlet>
      <servlet-name>
          Hello
      </servlet-name>
      <servlet-class>
          Hello
      </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/Hello</url-pattern>
    </servlet-mapping>

修改 web.xml 之後請記得重新啟動 Tomcat 服務(參考 6.0 的第一項),再以瀏覽器檢視網址: http://127.0.0.1/myapp/hello.htm

如果這個範例也順利完成的話,你在佈署 servlet 方面應該都沒問題了,可以試著練習寫複雜一點的範例程式。

6.0 其他事項

6.1 讓 Tomcat 重新載入 servlet

在撰寫 servlet 時,你可能會反覆修改程式,部署檔案,並且在瀏覽器中觀看修改後的結果。但是在預設的情況下,基於效能的考量,Tomcat 不會自動載入新的 servlet,這對我們在開發除錯時期很不方便。要讓新的 servlet 生效,有下列幾種方法可以使用,依我個人的喜好順序列出:
  1. 修改 Tomcat 的 server.xml 檔案內容,該檔案存在 Tomcat 的 conf 目錄下。做法是在檔案中加入一個新的 context 標籤,透過該標籤來設定你的 web 應用程式的環境參數。最簡單的方法就是先以字串搜尋的方式找到 "Tomcat Root Context" 這個標籤,然後在這段文字的上面加入一行 <DefaultContext reloadable="true"/>,參考下面的範例:
    <DefaultContext reloadable="true"/> 
    
    <!-- Tomcat Root Context -->
    <!--
    <Context path="" docBase="ROOT" debug="0"/>
    -->

    這個設定只需要做一次就行了,所以最方便,完成後記得要重新啟動 Tomcat 伺服器,新的設定才會生效。

  2. 重新啟動 Tomcat 伺服器,你可以開啟〔控制台〕的〔系統管理工具〕中的〔服務〕,找到 "Apache Tomcat" 這個服務項目,在此項目上點一下滑鼠右鍵,選 "重新啟動"。
  3. 修改(touch)佈署描述檔 web.xml,只要 web.xml 檔案有被修改過,Tomcat 會自動偵測並重新載入該檔案所包含的 servlets。
  4. 在瀏覽器的網址列輸入 "http://localhost:8080/manager/reload?path=要重新啟動的應用程式路徑",例如本文中的範例就是:"http://localhost:8080/manager/reload?path=/myapp"。在執行新載入前會求你輸入管理者的帳號和密碼(只需輸入一次),若執行成功,則會顯示 "Ok - Reloaded application at context path ***"。

由於瀏覽器本身也有快取機制,如果重新整理仍無法看到修改後的結果,你可以試試看將瀏覽器的快取功能關閉,IE6 的設定在〔工具\網際網路選項\一般〕的〔設定〕鈕,預設是自動檢查網頁是否有新版本,你可以試著將它改為 "每次查閱畫面時" 檢查是否有新版的檔案。

7.0 學習評量

做完練習後,問你自己以下問題,不知道的地方請查閱相關書籍。

  1. 什麼是 Web container?什麼是 Java servlet?
  2. Web.xml 檔案的用途是?
  3. Java 程式裡面的的 import 是做什麼用的?
  4. 範例程式中的 Java 類別都繼承自 HttpServlet,這個類別的主要用途是什麼?它有哪些屬性?經常需要改寫的方法有哪些?
  5. 試說明瀏覽器和 servlet 之間的互動過程。
  6. 範例程式中的 Java 類別都有個 doGet 方法,它的作用是什麼?
  7. 說明 HTTP 的 GET 和 POST 方法的異同。
  8. doGet 方法的簽名(signature)後面都有宣告 throws ServletException, IOException,其作用為何?不宣告 exception 會怎麼樣?
  9. 範例程式使用的是 HTTP 的 GET 方法,試改寫成 POST 方法。
  10. PrintWriter 類別的作用是?

參考文獻

[1] Java Servlet 程式設計(第二版),楊協龍、謝鎮澤 譯,歐萊禮,2002。

[2] http://javaboutique.internet.com/tutorials/Tomcat/(詳細的 Tomcat 安裝與設定說明)。