Spring @PreDestroy:没有记录,因为 Logback 停止得太快
Spring @PreDestroy: No logging because Logback stops too soon
在我的项目中,我使用 Logback 作为日志工具。我有以下 class
@Component
class Test {
@PreDestroy
public void destroy() {
try {
...
} catch (Exception e) {
LoggerFactory.getLogger(getClass()).error(e.getLocalizedMessage(), e);
}
}
}
现在,我取消部署 servlet。发生异常时,Logback 不会打印消息和堆栈跟踪。这是因为在 Spring 调用 destroy()
之前,Logback 正在清理。取消部署 servlet 时,这是第一个(也是最后一个)日志行:
15:46:19,084 |-INFO in ch.qos.logback.classic.servlet.LogbackServletContextListener@7957fe56 - About to stop ch.qos.logback.classic.LoggerContext [default]
我通过在 destroy()
中添加 System.out.println("...");
来验证 Logback 首先停止。
有什么办法可以解决这个问题吗?
我的依赖项:
<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-jcl
用于将 commons-logging
路由到 slf4j
(这将路由到 logback
)。我没有使用 jcl-over-slf4j
.
有一个documented way禁用来禁用LogbackServletContextListener
:
的注册
You may disable the automatic the installation of
LogbackServletContextListener by setting a named
logbackDisableServletContainerInitializer in your web-application's
web.xml file. Here is the relevant snippet.
<web-app>
<context-param>
<param-name>logbackDisableServletContainerInitializer</param-name>
<param-value>true</param-value>
</context-param>
....
</web-app>
Note that logbackDisableServletContainerInitializer variable can also be set as a Java system property an OS environment variable. The most local setting has priority, i.e. web-app first, system property second and OS environment last.
我想如果是这种情况,您可能想编写自己的关闭钩子并停止 LoggerContext
获取Dovmo 的答案。这都是关于订购的。我在 Tomcat 8.5.x 上遇到了同样的问题。基本上,初始化程序执行 addListener
,您无法控制侦听器。在关闭时,Tomcat 反向迭代该列表,首先选择 Logback 侦听器:Spring 不会记录任何内容。
自定义侦听器无济于事,因为您无法将其添加到前面。 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>
在我的项目中,我使用 Logback 作为日志工具。我有以下 class
@Component
class Test {
@PreDestroy
public void destroy() {
try {
...
} catch (Exception e) {
LoggerFactory.getLogger(getClass()).error(e.getLocalizedMessage(), e);
}
}
}
现在,我取消部署 servlet。发生异常时,Logback 不会打印消息和堆栈跟踪。这是因为在 Spring 调用 destroy()
之前,Logback 正在清理。取消部署 servlet 时,这是第一个(也是最后一个)日志行:
15:46:19,084 |-INFO in ch.qos.logback.classic.servlet.LogbackServletContextListener@7957fe56 - About to stop ch.qos.logback.classic.LoggerContext [default]
我通过在 destroy()
中添加 System.out.println("...");
来验证 Logback 首先停止。
有什么办法可以解决这个问题吗?
我的依赖项:
<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-jcl
用于将 commons-logging
路由到 slf4j
(这将路由到 logback
)。我没有使用 jcl-over-slf4j
.
有一个documented way禁用来禁用LogbackServletContextListener
:
You may disable the automatic the installation of LogbackServletContextListener by setting a named logbackDisableServletContainerInitializer in your web-application's web.xml file. Here is the relevant snippet.
<web-app> <context-param> <param-name>logbackDisableServletContainerInitializer</param-name> <param-value>true</param-value> </context-param> .... </web-app>
Note that logbackDisableServletContainerInitializer variable can also be set as a Java system property an OS environment variable. The most local setting has priority, i.e. web-app first, system property second and OS environment last.
我想如果是这种情况,您可能想编写自己的关闭钩子并停止 LoggerContext
获取Dovmo 的答案。这都是关于订购的。我在 Tomcat 8.5.x 上遇到了同样的问题。基本上,初始化程序执行 addListener
,您无法控制侦听器。在关闭时,Tomcat 反向迭代该列表,首先选择 Logback 侦听器:Spring 不会记录任何内容。
自定义侦听器无济于事,因为您无法将其添加到前面。 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>