【发布时间】:2016-02-24 00:02:49
【问题描述】:
我正在尝试向记录器写入一条消息,表明(Vaadin)servlet 已停止,这使用 SLF4J 和 Log4j2。
为此,我使用了ServletContextListener,它会在应用程序启动时记录一条消息。但是,在contextDestroyed 方法内登录时,我无法获得任何输出...这是我的实现:
@WebListener
public class VaadinLogger implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger(VaadinLogger.class);
@Override
public void contextInitialized(ServletContextEvent contextEvent) {
// Remove appenders from JUL loggers
SLF4JBridgeHandler.removeHandlersForRootLogger();
// Install bridge
SLF4JBridgeHandler.install();
// Get servlet context
ServletContext context = contextEvent.getServletContext();
// Retrieve name
String name = context.getServletContextName();
// Log servlet init information
logger.info("Start \"{}\"", name);
}
@Override
public void contextDestroyed(ServletContextEvent contextEvent) {
// Get servlet context
ServletContext context = contextEvent.getServletContext();
// Retrieve name
String name = context.getServletContextName();
// Log servlet destroy information
logger.info("End \"{}\"{}", name, System.lineSeparator()));
// Uninstall bridge
SLF4JBridgeHandler.uninstall();
}
}
此时,我猜这可能是因为在调用 contextDestroyed 时,不再可能进行日志记录,因为它们已经被垃圾收集器销毁了。
所以现在我的问题是,是否可以在销毁上下文之前记录 servlet 已停止,或者在销毁 log4j2 记录器之前执行上下文侦听器?
提前致谢!
【问题讨论】:
-
如果您有对记录器的实时引用,那么它不会被垃圾收集。你确定
ServletContext真的已经被销毁了吗?是什么导致了它的破坏? -
我希望在我停止 tomcat 服务器时上下文被破坏。我认为这是有效的,因为
SLF4JBridgeHandler.uninstall();修复了我的控制台输出中的一些错误。此外,当我将logger.info(...更改为System.out.println(...时,消息会打印到控制台。 -
您是优雅地关闭了容器,还是突然终止了 JVM?我经常看到使用 Eclipse 的初学者认为 Console 选项卡上的红色按钮会优雅地关闭容器,但实际上它会立即杀死 JVM。您应该改用 Servers 选项卡上的红色按钮(或右键单击服务器并选择“停止”)。
-
是的,我之前确实注意到了这一点,所以从那以后我一直使用服务器选项卡中的停止按钮来停止服务器。所以不幸的是这不是问题......
-
我们在 logback 中遇到了类似的问题,并解决了这个问题:stackoverflow.com/a/49816008/7305670
标签: java servlets logging slf4j log4j2