鍍金池/ 教程/ Java/ 調(diào)試
發(fā)送電子郵件
調(diào)試
異常處理
自動(dòng)刷新頁面
處理日期
實(shí)例
生命周期
數(shù)據(jù)庫訪問
國際化
會(huì)話跟蹤
環(huán)境設(shè)置
客戶端 HTTP 請(qǐng)求
文件上傳
頁面重定向
服務(wù)器 HTTP 響應(yīng)
編寫過濾器
表單數(shù)據(jù)
HTTP 狀態(tài)碼
Cookies 處理
概述
點(diǎn)擊計(jì)數(shù)器

調(diào)試

測(cè)試/調(diào)試 servlet 始終是困難的。Servlets 往往涉及大量的客戶端/服務(wù)器交互,可能會(huì)出現(xiàn)錯(cuò)誤但是又難以重現(xiàn)。

這里有一些提示和建議,可以幫助你調(diào)試。

System.out.println()

System.out.println() 作為一個(gè)標(biāo)記用來測(cè)試某一代碼片段是否被執(zhí)行,使用方法非常簡(jiǎn)單。我們也可以輸出變量值。另外:

  • 由于 System 對(duì)象是核心 Java 對(duì)象的一部分,它可以用于任何不需要安裝任何額外類的地方。這包括 Servlets、JSP、RMI、EJB's、普通的 Beans 和類,以及獨(dú)立的應(yīng)用程序。

  • 與在斷點(diǎn)處停止相比,寫入 System.out 不會(huì)對(duì)應(yīng)用程序的正常執(zhí)行流程有太多干擾,這使得它在時(shí)序重要的時(shí)候顯得非常有價(jià)值。

以下使用 System.out.println() 的語法:

System.out.println("Debugging message");

通過上述語法生成的所有消息將被記錄在 web 服務(wù)器的日志文件中。

消息記錄

利用標(biāo)準(zhǔn)日志記錄方法,使用適當(dāng)?shù)娜罩居涗浄椒▉碛涗浰姓{(diào)試、警告和錯(cuò)誤消息是非常好的想法,我使用的是 log4J 來記錄所有的消息。

Servlet API 還提供了一個(gè)簡(jiǎn)單的輸出信息的方式,使用 log() 方法,如下所示:

// Import required java libraries
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");
      //Call the two ServletContext.log methods
      ServletContext context = getServletContext( );
      if (par == null || par.equals(""))
      //log version with Throwable parameter
      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 目錄中找到。

這些日志文件確實(shí)為新出現(xiàn)的錯(cuò)誤或問題的頻率給出了指示。正因?yàn)槿绱?,在通常不?huì)出現(xiàn)的異常 catch 子句中使用 log() 函數(shù)是很好的。

使用 JDB 調(diào)試器

你可以使用調(diào)試 applet 或應(yīng)用程序的相同的 jdb 命令來調(diào)試 servlet。

為了調(diào)試一個(gè) servlet,我們可以調(diào)試 sun.servlet.http.HttpServer,然后把它看成是 HttpServer 執(zhí)行 servlet 來響應(yīng)來自瀏覽器端的 HTTP 請(qǐng)求。這與調(diào)試 applet 小程序的方式非常相似。與調(diào)試 applet 不同的是,被調(diào)試的實(shí)際程序是 sun.applet.AppletViewer。

大多數(shù)調(diào)試器會(huì)自動(dòng)隱藏了解如何調(diào)試 applet 的細(xì)節(jié)。直到他們?yōu)?servlet 做同樣的事情,你必須做以下操作來幫助你的調(diào)試器:

  • 設(shè)置你的調(diào)試器的類路徑,以便它可以找到 sun.servlet.http.Http-Server 和相關(guān)的類。

  • 設(shè)置你的調(diào)試器的類路徑,以便它可以找到你的 servlet 和支持的類,通常是在 server_root/servlets 和 server_root/classes 中。

你通常不會(huì)希望 server_root/servlets 在你的 classpath 中,因?yàn)樗鼤?huì)禁用 servlet 的重載。然而這種包含對(duì)于調(diào)試是有用的。在 HttpServer 中的自定義的 servlet 加載器加載 servlet 之前,它允許你的調(diào)試器在 servlet 中設(shè)置斷點(diǎn)。

一旦你設(shè)置了正確的類路徑,就可以開始調(diào)試 sun.servlet.http.HttpServer。你可以在任何你想要調(diào)試的 servlet 中設(shè)置斷點(diǎn),然后使用 web 瀏覽器為給定的 servlet(http://localhost:8080/servlet/ServletToDebug) 向 HttpServer 發(fā)出請(qǐng)求。你會(huì)看到程序執(zhí)行到你設(shè)置的斷點(diǎn)處停止。

使用注釋

代碼中的注釋有助于以各種方式調(diào)試程序。注釋可用于調(diào)試過程中的許多其他方式中。

Servlet 使用 Java 注釋,單行注釋(//...)和多行注釋(/ .../)可用于暫時(shí)移除部分 Java 代碼。如果 bug 消失,仔細(xì)看看你之前注釋的代碼并找出問題所在。

客戶端和服務(wù)器端頭信息

有時(shí),當(dāng)一個(gè) servlet 并沒有像預(yù)期那樣工作時(shí),查看原始的 HTTP 請(qǐng)求和響應(yīng)是非常有用的。如果你對(duì) HTTP 結(jié)構(gòu)很熟悉,你可以閱讀請(qǐng)求和響應(yīng),看看這些頭信息中究竟是什么。

重要的調(diào)試技巧

這里是 servlet 調(diào)試中的一些調(diào)試技巧列表:

  • 請(qǐng)注意 server _ root/classes 不會(huì)重載,而 server_root/servlets 可能會(huì)。

  • 要求瀏覽器顯示它所顯示的頁面的原始內(nèi)容。這有助于識(shí)別格式的問題。它通常是視圖菜單下的一個(gè)選項(xiàng)。

  • 通過強(qiáng)制執(zhí)行完全重載頁面,來確保瀏覽器還沒有緩存前一個(gè)請(qǐng)求的輸出。在 Netscape Navigator 中,使用 Shift-Reload;在 IE 瀏覽器中,請(qǐng)使用 Shift-Refresh。

  • 確認(rèn) servlet 的 init() 方法接受一個(gè) ServletConfig 參數(shù)并立即調(diào)用 super.init(config)。