Servlets 简明教程

Servlets - Debugging

测试/调试 servlet 总是一件困难的事情。servlet 往往涉及大量客户端/服务器交互,因此错误可能很频繁,但难以重现。

以下是一些技巧和建议,可以帮助您进行调试。

System.out.println()

System.out.println() 易于用作标记,以测试程序的某个部分是否正在执行。我们还可以打印出变量值。此外 −

  1. 由于 System 对象是核心 Java 对象的一部分,因此可以在任何地方使用它,而无需安装任何其他类。这包括 Servlet、JSP、RMI、EJB、普通 Bean 和类,以及独立应用程序。

  2. 断点技术会停止正常执行,因此会花费更多的时间。而写入 System.out 不会过多地干扰应用程序的正常执行流程,这在时间至关重要时非常有价值。

以下是如何使用 System.out.println() 的语法 −

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

通过上述语法生成的所有消息都将记录在 Web 服务器日志文件中。

Message Logging

使用标准日志方法记录所有调试、警告和错误消息始终是一个好主意。我使用 log4J 记录所有消息。

Servlet API 还提供了一种通过使用 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 安装目录>/logs。

日志文件确实提示了新出现的错误或问题的发生频率。因此,在通常不应该发生的异常的 catch 子句中使用 log() 函数效果不错。

Using JDB Debugger

您可以使用与用于调试 applet 或应用程序相同的 jdb 命令来调试 serlet。

要调试 serlet,我们调试 sun.servlet.http.HttpServer,并在 HttpServer 响应来自浏览器 HTTP 请求执行 servlet 时仔细观察行为。这与调试小程序非常相似。不同之处在于,对于小程序,要调试的实际程序是 sun.applet.AppletViewer。

大多数调试器通过自动了解如何调试小程序隐藏此详细信息。直到它们对 servlet 执行相同的操作,您才必须通过执行以下操作帮助您的调试器 −

  1. 设置调试器的类路径,以便它可以查找 sun.servlet.http.Http-Server 及其关联类。

  2. 设置调试器的类路径,以便它还可以查找您的 servlet 和支持类,通常为 server_root/servlets 和 server_root/classes。

您通常不希望将 server_root/servlets 放入类路径,因为它会禁用 servlet 重新加载。但是,此包含项对调试很有用。它允许您的调试器在 HttpServer 中的自定义 servlet 加载器加载 servlet 之前在 servlet 中设置断点。

设置好正确的类路径后,开始调试 sun.servlet.http.HttpServer。您可以在您想要调试的任何 servlet 中设置断点,然后使用网络浏览器向 HttpServer 发出对给定 servlet 的请求([role="bare"] [role="bare"]http://localhost:8080/servlet/ServletToDebug )。您应该看到执行在您的断点处停止。

Using Comments

代码中的注释可以通过多种方式帮助调试过程。注释可以在调试过程中的许多其他方式中使用。

Servlet 使用 Java 注释,并且可以使用单行(// …​)和多行(/* …​ */)注释来临时删除 Java 代码的部分。如果错误消失了,请仔细查看您刚刚注释的代码并找出问题。

Client and Server Headers

有时,当 servlet 未按预期运行时,查看原始 HTTP 请求和响应非常有用。如果您熟悉 HTTP 的结构,您可以读取请求和响应,并确切地了解那些标头正在做什么。

Important Debugging Tips

此处列出了一些有关 servlet 调试的其他调试提示 −

  1. 请记住,server_root/classes 不重新加载,而 server_root/servlet 可能重新加载。

  2. 要求浏览器显示它正在显示的页面的原始内容。这有助于识别格式问题。它通常是“查看”菜单下的一个选项。

  3. 通过强制重新加载整个页面,确保浏览器不会缓存前一个请求的输出。使用 Netscape Navigator 时,使用 Shift-Reload;使用 Internet Explorer 时,使用 Shift-Refresh。

  4. 验证 servlet 的 init() 方法是否获取 ServletConfig 参数并立即调用 super.init(config)。