Servlet 調試
測試/偵錯 Servlet 始終是開發使用過程中的困難點。 Servlet 往往涉及大量的客戶端/伺服器交互,可能會出現錯誤但又難以重現。
這裡有一些提示和建議,可以幫助您除錯。
System.out.println()
System.out.println() 是作為一個標記來使用的,用來測試一段特定的程式碼是否被執行。我們也可以印出變數的值。此外:
由於 System 物件是核心 Java 物件的一部分,它可以在不需要安裝任何額外類別的情況下被用於任何地方。這包括 Servlet、JSP、RMI、EJB's、普通的 Beans 和類,以及獨立的應用程式。
與在斷點處停止不同,寫入到System.out 不會幹擾到應用程式的正常執行流程,這使得它在時序是至關重要的時候顯得尤為有價值。
以下是使用 System.out.println() 的語法:
System.out.println("Debugging message");
透過上面的語法產生的所有訊息將記錄在 Web 伺服器日誌檔案中。
訊息日誌
使用適當的日誌記錄方法來記錄所有偵錯、警告和錯誤訊息,這是非常好的想法,推薦使用log4J 來記錄所有的消息。
Servlet API 也提供了一個簡單的輸出資訊的方式,使用log() 方法,如下所示:
// 导入必需的 java 库 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ContextLog extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { String par = request.getParameter("par1"); // 调用两个 ServletContext.log 方法 ServletContext context = getServletContext( ); if (par == null || par.equals("")) // 通过 Throwable 参数记录版本 context.log("No message received:", new IllegalStateException("Missing parameter")); else context.log("Here is the visitor's message: " + par); response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter( ); String title = "Context Log"; String docType = "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n"; out.println(docType + "<html>\n" + "<head><title>" + title + "</title></head>\n" + "<body bgcolor=\"#f0f0f0\">\n" + "<h1 align=\"center\">" + title + "</h1>\n" + "<h2 align=\"center\">Messages sent</h2>\n" + "</body></html>"); } //doGet }
ServletContext 把它的文字訊息記錄到Servlet 容器的日誌檔案中。對於 Tomcat,這些日誌可以在 <Tomcat-installation-directory>/logs 目錄中找到。
這些日誌檔案確實對新出現的錯誤或問題的頻率給予指示。正因為如此,建議在通常不會發生的異常的 catch 子句中使用 log() 函數。
使用 JDB 偵錯器
您可以使用偵錯 applet 或應用程式的 jdb 命令來偵錯 Servlet。
為了偵錯一個 Servlet,我們可以偵錯 sun.servlet.http.HttpServer,然後把它看成是 HttpServer 執行 Servlet 來回應瀏覽器端的 HTTP 請求。這與調試 applet 小程式非常相似。與調試 applet 不同的是,實際被調試的程式是 sun.applet.AppletViewer。
大多數偵錯器會自動隱藏如何偵錯 applet 的細節。同樣的,對於servlet,您必須幫偵錯器執行以下操作:
設定您的偵錯器的類別路徑classpath,以便它可以找到sun.servlet.http.Http-Server和相關的類別。
設定您的偵錯器的類路徑 classpath,以便它可以找到您的 servlet 和支援的類,通常是在 server_root/servlets 和 server_root/classes 中。
您通常不會希望 server_root/servlets 在您的 classpath 中,因為它會停用 servlet 的重新載入。但是這種包含規則對於調試是非常有用的。它允許您的偵錯器在 HttpServer 中的自訂 Servlet 載入器載入 Servlet 之前在 Servlet 中設定斷點。
如果您已經設定了正確的類別路徑 classpath,您可以開始偵錯 sun.servlet.http.HttpServer。可以在您想要偵錯的 Servlet 程式碼中設定斷點,然後透過 Web 瀏覽器使用給定的 Servlet(http://localhost:8080/servlet/ServletToDebug)向 HttpServer 發出請求。您會看到程式執行到斷點處會停止。
使用註解
程式碼中的註解有助於以各種方式進行偵錯。註釋可用於調試過程的許多其他方式。
此 Servlet 使用 Java 註解和單行註解(//...),多行註解(/* ...*/)可用於暫時移除部分 Java 程式碼。如果 bug 消失,仔細看看您剛才註解的程式碼並找出問題所在。
客戶端和伺服器端頭資訊
有時,當一個 Servlet 並沒有像預期那樣時,查看原始的 HTTP 請求和回應是非常有用的。如果您熟悉 HTTP 結構,您可以閱讀請求和回應,看看這些頭資訊究竟是什麼。
重要的偵錯技巧
下面列出了一些Servlet 偵錯的技巧:
請注意,server_root/classes 不會重載,而server_root/servlets 可能會。
要求瀏覽器顯示它所顯示的頁面的原始內容。這有助於識別格式的問題。它通常是"視圖"選單下的選項。
透過強制執行完全重新載入頁面來確保瀏覽器還沒有快取前一個請求的輸出。在 Netscape Navigator 中,請使用 Shift-Reload,在 Internet Explorer 中,請使用 Shift-Refresh。
請確認 servlet 的 init() 方法接受一個 ServletConfig 參數,並呼叫 super.init(config)。