启动:日志记录应用程序筛选器干扰应用程序日志记录

2022-09-03 15:13:09

Spring Boot 使用 自动初始化底层日志记录系统。如果我正在开发的应用程序独立运行或独立运行,这是一件好事。LoggingApplicationListener

但是,我正在开发一个将部署到WSO2应用程序服务器的Web应用程序,该应用程序提供统一日志记录(使用log4j),并具有中央日志级别管理(运行时通过Web界面),业务报告等功能。

如果我“按原样”使用Spring Boot,它会完全自行记录所有内容。我的第一个镜头是,删除并手动添加为。这在一定程度上是有效的,因为现在覆盖了WSO2提供的全局日志管理器的设置(甚至导致全局追加器关闭)。spring-boot-starter-loggingslf4j-apiprovidedLoggingApplicationListener

我想出的唯一“解决方案”是通过反射来移除听众。然后Spring Boot开始完全按照它应有的方式运行(通过全局记录器进行日志记录,并且不覆盖预定义的日志级别,输出格式,追加器等)。

该“解决方案”如下所示:

@SpringBootApplication
public class MyApp extends SpringBootServletInitializer {

    public static void main(String... args) {
        SpringApplication.run(MyApp.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        try {
            Field appField = SpringApplicationBuilder.class.getDeclaredField("application");
            appField.setAccessible(true);
            SpringApplication app = (SpringApplication)appField.get(builder);

            Field listenersField = SpringApplication.class.getDeclaredField("listeners");
            listenersField.setAccessible(true);
            List<ApplicationListener<?>> listeners = (List<ApplicationListener<?>>) listenersField.get(app);
            for (int i = listeners.size() - 1; i >= 0; --i) {
                if (listeners.get(i) instanceof LoggingApplicationListener) {
                    listeners.remove(i);
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return builder.sources(MyApp.class);
    }
}

有没有更好的解决方案来解决我的问题,也许不那么黑客,我在研究和代码分析期间可能忽略了这一点?


答案 1

感谢您的帖子,这是非常有帮助的。我在Websphere Aplication Server上遇到了同样的问题:在弹簧引导上下文初始化后,我不再有日志。此解决方案是等效的,但通过重写 SpringBootServletInitializer 的运行方法而变得不那么脏:

@Override
    protected WebApplicationContext run(SpringApplication application) {
        Collection<ApplicationListener<?>> listeners =
                new ArrayList<>();
        for (ApplicationListener<?> listener: application.getListeners()) {
            if (!(listener instanceof LoggingApplicationListener)) {
                listeners.add(listener);
            }
        }
        application.setListeners(listeners);
        return super.run(application);
    }

答案 2

从 Spring Boot 1.4 开始,可以禁用 LoggingSystem 自动配置。

请查看 Spring 文档的“自定义日志配置”部分:

您可以通过使用 system 属性强制 Spring Boot 使用特定的日志记录系统。该值应为实现的完全限定类名。您还可以通过使用值 完全禁用 Spring Boot 的日志记录配置。org.springframework.boot.logging.LoggingSystemLoggingSystemnone

例如,对于 Tomcat,设置环境变量:JAVA_OPTS

JAVA_OPTS="-Dorg.springframework.boot.logging.LoggingSystem=none"

推荐