如何在Spring Boot应用程序中记录活动配置?

我真的很喜欢使用YAML配置为Spring Boot,因为我发现它非常可读和有用,有一个文件显示哪些属性是在我的不同的配置文件中活动。 不幸的是,我发现application.yml中的设置属性可能相当脆弱。

像使用tab而不是空格的东西会导致属性不存在(就我所知,没有警告),而且我经常发现我的活动配置文件没有被设置,因为我的YAML有一些未知的问题。

所以我想知道是否有任何钩子可以让我获得当前活动的配置文件和属性,以便我可以记录它们。

同样,如果application.yml包含错误,有没有办法导致启动失败? 要么是我自己validationYAML的手段,这样我就可以杀死启动过程。

我有同样的问题,并希望有一个调试标志,会告诉配置文件处理系统吐出一些有用的日志记录。 一种可能的方法是为您的应用程序上下文注册一个事件监听器,并从环境中打印配置文件。 我没有尝试过这样做自己,所以你的里程可能会有所不同。 我想也许像这里概述的东西:

如何将钩子添加到应用程序上下文初始化事件?

那么你可以在你的监听器中做这样的事情:

 System.out.println("Active profiles: " + Arrays.toString(ctxt.getEnvironment().getActiveProfiles())); 

也许值得尝试一下。 另一种方法,你可能会做到这一点将声明环境注入代码,你需要打印配置文件。 即:

 @Component public class SomeClass { @Autowired private Environment env; ... private void dumpProfiles() { // Print whatever needed from env here } } 

执行器/ env服务显示属性,但不显示实际活动的属性值。 很多时候你可能想要用你的应用程序属性覆盖

  • 配置文件特定应用程序属性
  • 命令行参数
  • OS环境variables

因此,您将在几个来源中拥有相同的属性和不同的值。

代码段下拉菜单在启动时打印活动的应用程序属性值:

 @Configuration public class PropertiesLogger { private static final Logger log = LoggerFactory.getLogger(PropertiesLogger.class); @Autowired private AbstractEnvironment environment; @PostConstruct public void printProperties() { log.info("**** APPLICATION PROPERTIES SOURCES ****"); Set properties = new TreeSet<>(); for (PropertiesPropertySource p : findPropertiesPropertySources()) { log.info(p.toString()); properties.addAll(Arrays.asList(p.getPropertyNames())); } log.info("**** APPLICATION PROPERTIES VALUES ****"); print(properties); } private List findPropertiesPropertySources() { List propertiesPropertySources = new LinkedList<>(); for (PropertySource propertySource : environment.getPropertySources()) { if (propertySource instanceof PropertiesPropertySource) { propertiesPropertySources.add((PropertiesPropertySource) propertySource); } } return propertiesPropertySources; } private void print(Set properties) { for (String propertyName : properties) { log.info("{}={}", propertyName, environment.getProperty(propertyName)); } } } 

如果application.yml包含错误,则会导致启动失败。 我想这取决于你的意思是“错误”,但。 如果YAML不健全,肯定会失败。 另外,如果您正在设置例如标记为ignoreInvalidFields=true @ConfigurationProperties ,或者设置了无法转换的值。 这是相当广泛的错误。

活动配置文件可能会在Environment实现启动时被记录下来(但是无论如何,你很容易抓住它并将其记录到启动程序代码中 – 环境的toString()将列出我认为活动的配置文件)。 如果添加执行器,则活动配置文件(或更多)也可在/ env端点中使用。

如果你想在初始化beans / application之前获得活动的配置文件,我唯一的方法是在SpringApplication / Builder中注册一个自定义的Banner。

除了其他答案:记录上下文刷新事件的活动属性。

Java 8

 package mypackage; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.EventListener; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Slf4j @Component public class AppContextEventListener { @EventListener public void handleContextRefreshed(ContextRefreshedEvent event) { printActiveProperties((ConfigurableEnvironment) event.getApplicationContext().getEnvironment()); } private void printActiveProperties(ConfigurableEnvironment env) { System.out.println("************************* ACTIVE APP PROPERTIES ******************************"); List propertySources = new ArrayList<>(); env.getPropertySources().forEach(it -> { if (it instanceof MapPropertySource && it.getName().contains("applicationConfig")) { propertySources.add((MapPropertySource) it); } }); propertySources.stream() .map(propertySource -> propertySource.getSource().keySet()) .flatMap(Collection::stream) .distinct() .sorted() .forEach(key -> { try { System.out.println(key + "=" + env.getProperty(key)); } catch (Exception e) { log.warn("{} -> {}", key, e.getMessage()); } }); System.out.println("******************************************************************************"); } } 

科特林

 package mypackage import mu.KLogging import org.springframework.context.event.ContextRefreshedEvent import org.springframework.context.event.EventListener import org.springframework.core.env.ConfigurableEnvironment import org.springframework.core.env.MapPropertySource import org.springframework.stereotype.Component @Component class AppContextEventListener { companion object : KLogging() @EventListener fun handleContextRefreshed(event: ContextRefreshedEvent) { printActiveProperties(event.applicationContext.environment as ConfigurableEnvironment) } fun printActiveProperties(env: ConfigurableEnvironment) { println("************************* ACTIVE APP PROPERTIES ******************************") env.propertySources .filter { it is MapPropertySource } .map { it as MapPropertySource } .filter { it.name.contains("applicationConfig") } .map { it -> it.source.keys } .flatMap { it } .distinctBy { it } .sortedBy { it } .forEach { it -> try { println("$it=${env.getProperty(it)}") } catch (e: Exception) { logger.warn("$it -> ${e.message}") } } println("******************************************************************************") } } 

输出如:

 ************************* ACTIVE APP PROPERTIES ****************************** server.port=3000 spring.application.name=my-app ... 2017-12-29 13:13:32.843 WARN 36252 --- [ main] m.AppContextEventListener : spring.boot.admin.client.service-url -> Could not resolve placeholder 'management.address' in value "http://${management.address}:${server.port}" ... spring.datasource.password= spring.datasource.url=jdbc:postgresql://localhost/my_db?currentSchema=public spring.datasource.username=db_user ... ******************************************************************************