春季@PreDestroy:无日志记录,因为 Logback 停止得太快

2022-09-03 07:44:37

在我的项目中,我使用Logback作为日志记录工具。我有以下课程

@Component
class Test {
    @PreDestroy
    public void destroy() {
        try {
            ...
        } catch (Exception e) {
            LoggerFactory.getLogger(getClass()).error(e.getLocalizedMessage(), e);
        }
    }
}

现在,我取消部署了 servlet。发生异常时,Logback 不会打印消息和堆栈跟踪。这是因为 Logback 在 Spring 调用之前正在清理。取消部署 servlet 时,这是第一个(也是最后一个)日志行:destroy()

15:46:19,084 |-INFO in ch.qos.logback.classic.servlet.LogbackServletContextListener@7957fe56 - About to stop ch.qos.logback.classic.LoggerContext [default]

我验证了 Logback 首先通过在 .System.out.println("...");destroy()

有没有办法解决这个问题?

我的依赖关系:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>5.0.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>99-empty</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-access</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jcl</artifactId>
    </dependency>
</dependencies>

请注意,用于路由到(将路由到 )。我没有使用.spring-jclcommons-loggingslf4jlogbackjcl-over-slf4j


答案 1

有一种有文档记录的禁用方法可以禁用:LogbackServletContextListener

您可以通过在 Web 应用程序的 web.xml文件中设置命名的 logbackDisableServletContainerInitializer 来禁用 LogbackServletContextListener 的自动安装。下面是相关代码段。

<web-app>
    <context-param>
        <param-name>logbackDisableServletContainerInitializer</param-name>
        <param-value>true</param-value>
    </context-param>
    .... 
</web-app>

请注意,logbackDisableServletContainerInitializer 变量也可以设置为 Java 系统属性和操作系统环境变量。最本地的设置具有优先级,即 Web 应用优先,系统属性第二,操作系统环境最后。

我想你可能会想写你自己的关机钩子,如果是这种情况,并停止LoggerContext


答案 2

拿起多夫莫的答案。一切都与订购有关。我在Tomcat 8.5.x上也有同样的问题。实际上,初始值设定项执行 ,您无法控制侦听器。在关机时,Tomcat 会反向迭代该列表,首先选择 Logback 侦听器:Spring 不会记录任何内容。addListener

自定义侦听器无济于事,因为您无法将其预置。在Tomcat上对我有用的是:

<listener>
    <listener-class>ch.qos.logback.classic.servlet.LogbackServletContextListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>logbackDisableServletContainerInitializer</param-name>
    <param-value>true</param-value>
</context-param>

推荐