測試/調試 Servlet 始終是開發(fā)使用過程中的難點。Servlet 往往涉及大量的客戶端/服務器交互,可能會出現(xiàn)錯誤但又難以重現(xiàn)。
這里有一些提示和建議,可以幫助您調試。
System.out.println() 是作為一個標記來使用的,用來測試一段特定的代碼是否被執(zhí)行。我們也可以打印出變量的值。此外:
由于 System 對象是核心 Java 對象的一部分,它可以在不需要安裝任何額外類的情況下被用于任何地方。這包括 Servlet、JSP、RMI、EJB's、普通的 Beans 和類,以及獨立的應用程序。
與在斷點處停止不同,寫入到 System.out 不會干擾到應用程序的正常執(zhí)行流程,這使得它在時序是至關重要的時候顯得尤為有價值。
下面是使用 System.out.println() 的語法:
System.out.println("Debugging message");
通過上面的語法生成的所有消息將被記錄在 Web 服務器日志文件中。
使用適當?shù)娜罩居涗浄椒▉碛涗浰姓{試、警告和錯誤消息,這是非常好的想法,推薦使用 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 參數(shù)記錄版本 context.log("No message received:", new IllegalStateException("Missing parameter")); else context.log("Here is the visitor's message: " + par); response.setContentType("text/html;charset=UTF-8"); java.io.PrintWriter out = response.getWriter( ); String title = "Context Log"; String docType = "<!DOCTYPE html> \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 目錄中找到。
這些日志文件確實對新出現(xiàn)的錯誤或問題的頻率給出指示。正因為如此,建議在通常不會發(fā)生的異常的 catch 子句中使用 log() 函數(shù)。
您可以使用調試 applet 或應用程序的 jdb 命令來調試 Servlet。
為了調試一個 Servlet,我們可以調試 sun.servlet.http.HttpServer,然后把它看成是 HttpServer 執(zhí)行 Servlet 來響應瀏覽器端的 HTTP 請求。這與調試 applet 小程序非常相似。與調試 applet 不同的是,實際被調試的程序是 sun.applet.AppletViewer。
大多數(shù)調試器會自動隱藏如何調試 applet 的細節(jié)。同樣的,對于 servlet,您必須幫調試器執(zhí)行以下操作:
設置您的調試器的類路徑 classpath,以便它可以找到 sun.servlet.http.Http-Server 和相關的類。
設置您的調試器的類路徑 classpath,以便它可以找到您的 servlet 和支持的類,通常是在 server_root/servlets 和 server_root/classes 中。
您通常不會希望 server_root/servlets 在您的 classpath 中,因為它會禁用 servlet 的重新加載。但是這種包含規(guī)則對于調試是非常有用的。它允許您的調試器在 HttpServer 中的自定義 Servlet 加載器加載 Servlet 之前在 Servlet 中設置斷點。
如果您已經設置了正確的類路徑 classpath,就可以開始調試 sun.servlet.http.HttpServer??梢栽谀胍{試的 Servlet 代碼中設置斷點,然后通過 Web 瀏覽器使用給定的 Servlet(http://localhost:8080/servlet/ServletToDebug)向 HttpServer 發(fā)出請求。您會看到程序執(zhí)行到斷點處會停止。
代碼中的注釋有助于以各種方式進行調試。注釋可用于調試過程的很多其他方式中。
該 Servlet 使用 Java 注釋和單行注釋(//...),多行注釋(/* ...*/)可用于暫時移除部分 Java 代碼。如果 bug 消失,仔細看看您剛才注釋的代碼并找出問題所在。
有時,當一個 Servlet 并沒有像預期那樣時,查看原始的 HTTP 請求和響應是非常有用的。如果您熟悉 HTTP 結構,您可以閱讀請求和響應,看看這些頭信息究竟是什么。
下面列出了一些 Servlet 調試的技巧:
請注意,server_root/classes 不會重載,而 server_root/servlets 可能會。
要求瀏覽器顯示它所顯示的頁面的原始內容。這有助于識別格式的問題。它通常是"視圖"菜單下的一個選項。
通過強制執(zhí)行完全重新加載頁面來確保瀏覽器還沒有緩存前一個請求的輸出。在 Netscape Navigator 中,請使用 Shift-Reload,在 Internet Explorer 中,請使用 Shift-Refresh。
請確認 servlet 的 init() 方法接受一個 ServletConfig 參數(shù),并調用 super.init(config)。