Spring Boot:LoggingApplicationListener干扰Application Server日志记录

时间:2015-04-13 16:07:25

标签: java spring logging spring-boot wso2carbon

Spring Boot使用LoggingApplicationListener自动初始化基础日志系统。如果我正在开发的应用程序是孤立的或独立的,那么这是一件好事。

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

如果我“按原样”使用Spring Boot,它会完全记录所有内容。我的第一个镜头是移除spring-boot-starter-logging并手动将slf4j-api添加为provided。这在某种程度上起作用,因为LoggingApplicationListener现在覆盖了WSO2提供的全局logmanager的设置(甚至导致全局appender被关闭)。

我想出的唯一“解决方案”是通过反射删除监听器。然后Spring Boot开始表现得完全正常(通过全局记录器记录,而不是覆盖预定义的日志级别,输出格式,appender等)。

“解决方案”看起来像这样:

@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);
    }
}

对于我的问题有没有更好的解决方案,在我的研究和代码分析过程中,我可能忽略了这些问题?

2 个答案:

答案 0 :(得分:4)

谢谢你发帖它非常有帮助。 我遇到了与Websphere Aplication Server相同的问题:在初始化春季启动上下文后,我没有更多日志。通过覆盖SpringBootServletInitializer的run方法,此解决方案相当但不那么脏:

@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);
    }

答案 1 :(得分:1)

自Spring Boot 1.4起,可以禁用LoggingSystem自动配置。

查看Spring文档的Custom Log Configuration部分:

  

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

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

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