04. Servlet 异常处理&日志调试

本文介绍Servlet中的异常处理机制,包括如何使用<error-page>元素处理特定异常或HTTP状态码,以及如何利用请求属性来分析错误异常。同时提供了一个具体的错误处理Servlet示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Servlet 异常处理


  • 对于 Servlet 的异常处理,整个流程同 Java SE 中的 异常处理一样,一样使用 throw 抛出异常,在代码中捕获异常后进行处理,但是在 Servlet 中可以使用 <error-page> 元素来对特定的异常或 HTTP 状态码调用相应的 Servlet 进行处理;
  • Servlet 中的异常捕获机制是这样的:当一个 Servlet 抛出异常时,Web 容器在使用了 exception-type 的 web.xml 中搜索与抛出异常类型相匹配的配置;

在 web.xml 中进行配置
假如有一个命名为 error.ErrorHandler 的 Servlet 在 Web 应用抛出 404,403 状态码和 ServletException,IOException 时会被调用,其在 web.xml 中的配置如下:
 
<!--对ErrorHandler进行Servlet的配置和映射配置-->
<servlet>
    <servlet-name>ErrorHandler</servlet-name>
    <servlet-class>error.ErrorHandler</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ErrorHandler</servlet-name>
    <url-pattern>/ErrorHandler</url-pattern>
</servlet-mapping>
<!--进行错误状态码403,404的相关 error-page 配置-->
<error-page>
    <error-code>404</error-code>
    <location>/ErrorHandler</location>
</error-page>
<error-page>
    <error-code>403</error-code>
    <location>/ErrorHandler</location>
</error-page>
<!--进行ServletException,IOException异常相关的 error-page 配置-->
<error-page>
    <exception-type>javax.servlet.ServletException</exception-type>
    <location>/ErrorHandler</location>
</error-page>
<error-page>
    <exception-type>java.io.IOException</exception-type>
    <location>/ErrorHandler</location>
</error-page>
当然如果要对所有的异常类型配置一个通用的错误处理 Servlet,那么只要对 java.lang。Throwable配置error-page即可,如下:
 
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/ErrorHandler</location>
</error-page>

Servlet 异常请求属性
Servlet 中提供了一系列的可访问请求属性列表,用于分析错误异常的性质,在 Sevlet抛出异常时,相应的异常类型或状态码信息会被添加到这些请求属性列表中;
javax.servlet.error.status_code
该属性给出状态码,状态码可被存储,并在存储为 java.lang.Integer 数据类型后可被分析。
javax.servlet.error.exception_type
该属性给出异常类型的信息,异常类型可被存储,并在存储为 java.lang.Class 数据类型后可被分析。
javax.servlet.error.message
该属性给出确切错误消息的信息,信息可被存储,并在存储为 java.lang.String 数据类型后可被分析。
javax.servlet.error.request_uri
该属性给出有关 URL 调用 Servlet 的信息,信息可被存储,并在存储为 java.lang.String 数据类型后可被分析。
javax.servlet.error.exception
该属性给出异常产生的信息,信息可被存储,并在存储为 java.lang.Throwable 数据类型后可被分析。
javax.servlet.error.servlet_name
该属性给出 Servlet 的名称,名称可被存储,并在存储为 java.lang.String 数据类型后可被分析。
这些属性可以通过 request.getAttribute(String errorName) 获取,具体使用见下面实例;

Servlet 异常处理程序示例
以下简要地实现 error.ErrorHandler 类,相关的 web.xml 见上面;
 
package error
public class ErrorHandler extends GenericServlet {
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException{
        //获取异常信息
        Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");
        Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
        String servletName = (String)request.getAttribute("javax.servlet.error.servlet_name");
        if (servletName == null)
            servletName = "Unknown";
        String requestUri = (String)request.getAttribute("javax.servlet.error.request_uri");
        if (requestUri == null)
            requestUri = "Unknown";
        
        // 设置响应内容类型,也可以直接转发到JSP页面进行显示,或者直接发送到日志
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>\n" +
            "<html>\n" +
            "<head><title>Error</title></head>\n" +
            "<body>\n"+
            "<h1>Error</h1>\n");
        if (throwable == null && statusCode == null){
            out.println("<h2>Error message missing </h2>");
        }else if (statusCode != null) {
            out.println("Error code : " + statusCode);
        }else{
            out.println("<h2>Error Message</h2>");
            out.println("Servlet Name : " + servletName + "</br></br>");
            out.println("Error Type : " + throwable.getClass( ).getName( ) + "</br></br>");
            out.println("Request URI: " + requestUri + "<br><br>");
            out.println("Error message: " + throwable.getMessage( ));
        }
        out.println("</body></html>");
    }
}



Servlet 消息日志

  • 在进行 Servlet 的调试时,比较常用的有2种方法;
  • 一种同 Java SE 一样直接使用 System.out.println() 进行简单快捷地调试;
  • 另外一种是使用适当的日志记录方法,可以使用 log4j 来进行系统的日志记录,Servlet API 中提供了一种简单的日志输出方式,使用 GenericServlet 或 HttpServlet 的 log() 方法,或者 ServletContext 的 log() 方法;
  • 通过 Servlet API 生成的日志记录在 【Tomcat根目录/logs目录】中可以找到;
关于 GenericServlet、HttpServlet 、ServletContext 的 log() 方法的 API
log(String msg)向 Servlet 的日志文件中写入日志
log(String message,java.lang.Throwable throwable)向 Servlet 的日志文件中写入错误日志,和异常堆栈信息
以下是简单的代码示例;
 
public class Demo extends GenericServlet {
  public void service(ServletRequest request, ServletResponse response) throws ServletException,java.io.IOException {
    
      String par = request.getParameter("parameter1");
      
      ServletContext context = getServletContext( );
      if (par == null || par.equals(""))
          context.log("No message received:",new IllegalStateException("Missing parameter"));
      else
          context.log("Here is the visitor's message: " + par);
      
      //接下去的代码流程
      ....... 
    } 
}






24-Jun-2025 07:49:42.304 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/9.0.106 24-Jun-2025 07:49:42.308 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器构建: Jun 5 2025 19:02:30 UTC 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器版本号: 9.0.106.0 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 操作系统名称: Windows 10 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.版本: 10.0 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 架构: amd64 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 环境变量: C:\jdk-11.0.7 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java虚拟机版本: 11.0.7+8-LTS 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.供应商: Oracle Corporation 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: C:\Users\25230\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\1e0b5b64-db26-45a1-a2b7-4d9004a7876d 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: C:\develop\tomcat\apache-tomcat-9.0.106-windows-x64\apache-tomcat-9.0.106 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.lang=ALL-UNNAMED 24-Jun-2025 07:49:42.309 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.lang.invoke=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.lang.reflect=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.io=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.util=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.util.concurrent=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.config.file=C:\Users\25230\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\1e0b5b64-db26-45a1-a2b7-4d9004a7876d\conf\logging.properties 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote= 24-Jun-2025 07:49:42.310 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.port=1099 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.ssl=false 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.password.file=C:\Users\25230\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\1e0b5b64-db26-45a1-a2b7-4d9004a7876d\jmxremote.password 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.access.file=C:\Users\25230\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\1e0b5b64-db26-45a1-a2b7-4d9004a7876d\jmxremote.access 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.rmi.server.hostname=127.0.0.1 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djdk.tls.ephemeralDHKeySize=2048 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dsun.io.useCanonCaches=false 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dignore.endorsed.dirs= 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.base=C:\Users\25230\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\1e0b5b64-db26-45a1-a2b7-4d9004a7876d 24-Jun-2025 07:49:42.311 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.home=C:\develop\tomcat\apache-tomcat-9.0.106-windows-x64\apache-tomcat-9.0.106 24-Jun-2025 07:49:42.312 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.io.tmpdir=C:\develop\tomcat\apache-tomcat-9.0.106-windows-x64\apache-tomcat-9.0.106\temp 24-Jun-2025 07:49:42.315 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 使用APR版本[1.7.4]加载了基于APR的Apache Tomcat本机库[1.3.1]。 24-Jun-2025 07:49:42.315 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR功能:IPv6[true]、sendfile[true]、accept filters[false]、random[true]、UDS [true]。 24-Jun-2025 07:49:42.315 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL配置:useAprConnector[false],useOpenSSL[true] 24-Jun-2025 07:49:42.319 信息 [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL成功初始化 [OpenSSL 3.0.14 4 Jun 2024] 24-Jun-2025 07:49:42.447 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-nio-8080"] 24-Jun-2025 07:49:42.460 信息 [main] org.apache.catalina.startup.Catalina.load 服务器在[326]毫秒内初始化 24-Jun-2025 07:49:42.509 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina] 24-Jun-2025 07:49:42.509 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.106] 24-Jun-2025 07:49:42.523 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"] 24-Jun-2025 07:49:42.538 信息 [main] org.apache.catalina.startup.Catalina.start [77]毫秒后服务器启动 已连接到服务器 [2025-06-24 07:49:42,553] 工件 ssmd539t:war: 正在部署工件,请稍候… 24-Jun-2025 07:49:49.697 信息 [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 2025-06-24 07:49:49 -0 [RMI TCP Connection(2)-127.0.0.1] INFO - Root WebApplicationContext: initialization started 2025-06-24 07:49:50 -109 [RMI TCP Connection(2)-127.0.0.1] INFO - Refreshing Root WebApplicationContext: startup date [Tue Jun 24 07:49:50 CST 2025]; root of context hierarchy 2025-06-24 07:49:50 -186 [RMI TCP Connection(2)-127.0.0.1] INFO - Loading XML bean definitions from class path resource [spring/spring.xml] 2025-06-24 07:49:50 -466 [RMI TCP Connection(2)-127.0.0.1] INFO - Loading XML bean definitions from class path resource [spring/spring-mybatis.xml] 2025-06-24 07:49:51 -1415 [RMI TCP Connection(2)-127.0.0.1] ERROR - maxIdle is deprecated 2025-06-24 07:49:51 -1512 [RMI TCP Connection(2)-127.0.0.1] INFO - {dataSource-1} inited Tue Jun 24 07:49:52 CST 2025 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. 2025-06-24 07:49:52 -2419 [Druid-ConnectionPool-Create-2093990188] ERROR - create connection error, url: jdbc:mysql://127.0.0.1:3306/ssmd539t?useUnicode=true&amp;characterEncoding=UTF-8&amp;tinyInt1isBit=false, errorCode 0, state 08001 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值