Нет вывода журнала в contextDestroyed с использованием ServletContextListener & SLF4J
Я пытаюсь написать сообщение в журнал, что сервлет (Vaadin) остановился, используя 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
вызывается, регистрация больше невозможна, потому что они уже были уничтожены сборщиком мусора.
Итак, теперь мой вопрос: возможно ли либо зарегистрировать, что сервлет остановился до уничтожения контекста, либо заставить работать contextlistener до уничтожения регистраторов log4j2?
Заранее спасибо!
3 ответа
Начиная с log4j 2.14.1, вы можете отключить автоматическое выключение и добавить прослушиватель для остановки регистратора.
<context-param>
<!-- auto-shutdown stops log4j when the web fragment unloads, but that
is too early because it is before the listeners shut down. To
compensate, use a Log4jShutdownOnContextDestroyedListener and
register it before any other listeners which means it will shut
down *after* all other listeners. -->
<param-name>isLog4jAutoShutdownDisabled</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<!-- ensure logging stops after other listeners by registering
the shutdown listener first -->
<listener-class>
org.apache.logging.log4j.web.Log4jShutdownOnContextDestroyedListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Во-первых, есть ли в вашем classpath файлы log4j 2.x api, core и web jar? Log4j-web-2.x.jar также регистрирует прослушиватель контекста, используемый для выключения подсистемы ведения журнала при выгрузке веб-приложения.
Если ваш слушатель запустится после этого, вы больше не сможете ничего записывать.
Вы можете проверить, что происходит, установив <Configuration status="trace" ...
в вашем файле конфигурации log4j2.
log4j2 (log4j-web-xx.jar) поставляется с веб-фрагментом. Этот фрагмент содержит ServletContextListener. Порядок слушателей зависит от инициализации (см. Спецификация сервлета). По умолчанию: сначала ваше приложение, потом другие.
Вы можете изменить порядок, чтобы указать <absolut-ordering>
в вашем web.xml:
<web-app>
<absolute-ordering>
<name>log4j</name>
<others/>
</absolute-ordering>
Смотрите также: сервлет-30-веб-фрагмент xml