JSP 偵錯


要測試/除錯一個JSP或servlet程式總是那麼的難。 JSP和Servlets程式趨向於牽涉到大量客戶端/伺服器之間的交互,這很有可能會產生錯誤,很難重現出錯的環境。

接下來將會給出一些小技巧和小建議,來幫助您調試程式。


# 使用System.out.println()

System.out.println()可以很方便地標記一段程式碼是否被執行。當然,我們也可以列印出各種各樣的值。另外:

  • 自從System物件成為Java核心物件後,它便可以使用在任何地方而不用引入額外的類別。使用範圍包括Servlets,JSP,RMI,EJB's,Beans,類別和獨立應用。

  • 與在斷點處停止運作相比,用System.out進行輸出不會對應用程式的運作流程造成重大的影響,而這個特性在定時機制非常重要的應用程式中就顯得非常有用了。

接下來給了使用System.out.println()的語法:

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

這是使用System.out.print()的簡單範例:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>System.out.println</title></head>
<body>
<c:forEach var="counter" begin="1" end="10" step="1" >
   <c:out value="${counter-5}"/></br>
   <% System.out.println( "counter= " + 
                     pageContext.findAttribute("counter") ); %>
</c:forEach>
</body>
</html>

現在,如果運行上面的範例的話,它將會產生如下的結果:

-4
-3
-2
-1
0
1
2
3
4
5

如果使用的是Tomcat伺服器,您就能夠在logs目錄下的stdout.log文件中發現多出如下內容:

counter=1
counter=2
counter=3
counter=4
counter=5
counter=6
counter=7
counter=8
counter=9
counter=10

使用這種方法可以將變數和其它的資訊輸出至系統日誌中,用來分析並找出造成問題的深層原因。


# 使用JDB Logger

J2SE日誌框架可為任何執行在JVM中的類別提供日誌記錄服務。因此我們可以利用這個框架來記錄任何資訊。

讓我們來重寫以上程式碼,使用JDK中的logger API:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page import="java.util.logging.Logger" %>

<html>
<head><title>Logger.info</title></head>
<body>
<% Logger logger=Logger.getLogger(this.getClass().getName());%>

<c:forEach var="counter" begin="1" end="10" step="1" >
   <c:set var="myCount" value="${counter-5}" />
   <c:out value="${myCount}"/></br>
   <% String message = "counter="
                  + pageContext.findAttribute("counter")
                  + " myCount="
                  + pageContext.findAttribute("myCount");
                  logger.info( message );
   %>
</c:forEach>
</body>
</html>

它的運行結果與先前的類似,但是,它可以獲得額外的資訊輸出至stdout.log文件中。在這我們使用了logger中的info方法。下面我們給出stdout.log檔案中的一個快照:

24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=1 myCount=-4
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=2 myCount=-3
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=3 myCount=-2
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=4 myCount=-1
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=5 myCount=0
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=6 myCount=1
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=7 myCount=2
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=8 myCount=3
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=9 myCount=4
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=10 myCount=5

訊息可以使用各種優先權發送,透過使用sever(),warning(),info(),config(),fine() ,finer(),finest()方法。 finest()方法用來記錄最好的訊息,而sever()方法用來記錄最嚴重的資訊。

使用Log4J 框架來將訊息記錄在不同的檔案中,這些訊息基於嚴重程度和重要性來進行分類。


# 調試工具

NetBeans是樹形結構,是開源的Java綜合開發環境,支援開發獨立的Java應用程式和網頁應用程序,同時也支援JSP調試。

NetBeans支援以下幾個基本的偵錯功能:

  • 斷點

  • # 單步追蹤

  • # 觀察點

詳細的資訊可以查看NetBeans使用手冊。


# 使用JDB Debugger

可以在JSP和servlets中使用jdb指令來進行偵錯,就像偵錯普通的應用程式一樣。

通常,我們直接調試sun.servlet.http.HttpServer 物件來查看HttpServer在回應HTTP請求時執行JSP/Servlets的情況。這與調試applets非常相似。不同之處在於,applets程式實際調試的是sun.applet.AppletViewer。

大部分調試器在調試applets時都能夠自動忽略掉一些細節,因為它知道如何調試applets。如果想要將偵錯物件轉移到JSP身上,就需要做好以下兩點:

  • # 設定偵錯器的classpath,讓它能夠找到sun.servlet.http.Http-Server  和相關的類別。

  • 設定偵錯器的classpath,讓它能夠找到您的JSP檔案和相關的類別。

設定好classpath後,開始偵錯sun.servlet.http.Http-Server 。您可以在JSP檔案的任意地方設定斷點,只要你喜歡,然後使用瀏覽器發送一個請求給伺服器就應該可以看見程式停在了斷點處。


# 使用註解

程式中的註解在許多方面都對程式的調試起到一定的幫助作用。註釋可以用在調試程式的許多方面。

JSP使用Java註解。如果一個BUG消失了,就請仔細查看您剛註解過的程式碼,通常都能找出原因。


# 客戶端和伺服器的頭模組

有時候,當JSP沒有按照預定的方式運作時,查看未加工的HTTP請求和回應也是很有用的。如果對HTTP的結構很熟悉的話,您可以直接觀察request和response然後看看這些頭模組到底怎麼了。


# 重要調試技巧

這裡我們再透露兩個調試JSP的小技巧:

  • 使用瀏覽器顯示原始的頁面內容,用來區分是否為格式問題。這個選項通常在View選單下。

  • 確保瀏覽器在強制重新載入頁面時沒有捕獲先前的request輸出。若使用的是Netscape Navigator瀏覽器,則用Shift-Reload;若使用的是IE瀏覽器,則用Shift-Refresh。