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() 方法输出信息的简单方法,如下所示 −
// 导入所需的 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 参数的日志版本 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\">"; out.println(docType + "<html>" ++ "<head><title>" + title + "</title></head>" ++ "<body bgcolor = \"#f0f0f0\">" ++ "<h1 align = \"center\">" + title + "</h1>" ++ "<h2 align = \"center\">Messages sent</h2>" ++ "</body> </html>" ); } //doGet }
ServletContext 将其文本消息记录到 servlet 容器的日志文件中。对于 Tomcat,这些日志位于 <Tomcat-installation-directory>/logs 中。
日志文件确实会指示新出现的错误或问题发生的频率。因此,最好在异常的 catch 子句中使用 log() 函数,这些异常通常不会发生。
使用 JDB 调试器
您可以使用与调试小程序或应用程序相同的 jdb 命令来调试 servlet。
要调试 servlet,我们调试 sun.servlet.http.HttpServer,并仔细观察 HttpServer 如何响应来自浏览器的 HTTP 请求来执行 servlet。这与调试小程序的方式非常相似。不同之处在于,对于小程序,实际被调试的程序是 sun.applet.AppletViewer。
大多数调试器通过自动知道如何调试小程序来隐藏此细节。在它们对 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 浏览器向给定 servlet 的 HttpServer 发出请求 (http://localhost: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)。