Servlet - 调试



测试/调试 Servlet 总是很困难。Servlet 往往涉及大量的客户端/服务器交互,这使得错误很可能发生,但又难以重现。

以下是一些可能有助于您进行调试的提示和建议。

System.out.println()

System.out.println() 是一种易于使用的标记,用于测试某些代码是否正在执行。我们也可以打印出变量值。此外 -

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

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

以下是使用 System.out.println() 的语法 -

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

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

消息日志记录

使用适当的日志记录方法来记录所有调试、警告和错误消息,使用标准的日志记录方法始终是一个好主意。我使用 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() 函数是一个好主意。

使用 JDB 调试器

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

要调试 Servlet,我们调试 sun.servlet.http.HttpServer,并在 HttpServer 响应从浏览器发出的 HTTP 请求执行 Servlet 时仔细观察。这与调试 applet 的方式非常相似。区别在于,对于 applet,正在调试的实际程序是 sun.applet.AppletViewer。

大多数调试器通过自动知道如何调试 applet 来隐藏此细节。在它们对 Servlet 执行相同操作之前,您必须通过执行以下操作来帮助您的调试器 -

  • 设置调试器的类路径,以便它可以找到 sun.servlet.http.Http-Server 和相关的类。

  • 设置调试器的类路径,以便它还可以找到您的 Servlet 和支持类,通常是 server_root/servlets 和 server_root/classes。

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

设置正确的类路径后,开始调试 sun.servlet.http.HttpServer。您可以在您感兴趣的任何 Servlet 中设置断点,然后使用 Web 浏览器向 HttpServer 发出给定 Servlet 的请求 (https://127.0.0.1:8080/servlet/ServletToDebug)。您应该会看到执行在您的断点处停止。

使用注释

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

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

客户端和服务器标头

有时,当 Servlet 的行为不符合预期时,查看原始 HTTP 请求和响应很有用。如果您熟悉 HTTP 的结构,您可以读取请求和响应,并准确了解这些标头中发生了什么。

重要的调试技巧

以下是有关 Servlet 调试的一些更多调试技巧 -

  • 请记住,server_root/classes 不会重新加载,而 server_root/servlets 可能会重新加载。

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

  • 确保浏览器没有缓存先前请求的输出,方法是强制完全重新加载页面。使用 Netscape Navigator,使用 Shift-Reload;使用 Internet Explorer,使用 Shift-Refresh。

  • 验证您的 Servlet 的 init() 方法是否采用 ServletConfig 参数并立即调用 super.init(config)。

广告