转储Spring启动配置

问题描述 投票:0回答:4

我们的运维人员希望在应用程序启动时将 Spring boot 配置(即所有属性)转储到日志文件中。我认为这可以通过使用注释 @ConfigurationProperties 注入属性并打印它们来完成。

问题是是否有更好的或内置的机制来实现这一目标。

鉴于似乎没有内置的解决方案,我尝试自己做饭。这是我想到的:

@Component
public class ConfigurationDumper {


    @Autowired
    public void init(Environment env){
        log.info("{}",env);
    }

}

这样做的挑战是它不会打印我的 application.yml 中的变量。相反,这是我得到的:

StandardServletEnvironment 
{
    activeProfiles=[],
    defaultProfiles=[default],
    propertySources=[
        servletConfigInitParams,
        servletContextInitParams,
        systemProperties,
        systemEnvironment,
        random,
        applicationConfig: [classpath: /application.yml]
    ]
}

如何解决此问题以便加载和打印所有属性?

spring configuration spring-boot
4个回答
5
投票

如果您使用 actuator

env
endpoint 将为您提供
ConfigurableEnvironment
中设置的所有配置属性,而
configprops
将为您提供
@ConfigurationProperties
的列表,但不在日志中。

查看此 env 端点的

源代码
,也许它会让您了解如何获取您感兴趣的所有属性。


2
投票

没有内置机制,这实际上取决于您所说的“所有属性”的含义。您只想要you编写的实际键还是想要所有属性(包括默认值)。

对于前者,您可以轻松监听

ApplicationEnvironmentPreparedEvent
并记录您感兴趣的属性源。对于后者,
/configprops
确实是一个更好/完整的输出。


0
投票

这仅记录配置的属性 *.properties 文件。

/**
 * maps given property names to its origin
 * @return a map where key is property name and value the origin
 */
public Map<String, String> fromWhere() {
    final Map<String, String> mapToLog = new HashMap<>();

    final MutablePropertySources propertySources = env.getPropertySources();

    final Iterator<?> it = propertySources.iterator();

    while (it.hasNext()) {
        final Object object = it.next();
        if (object instanceof MapPropertySource) {
            MapPropertySource propertySource = (MapPropertySource) object;
            String propertySourceName = propertySource.getName();

            if (propertySourceName.contains("properties")) {

                Map<String, Object> sourceMap = propertySource.getSource();

                for (String key : sourceMap.keySet()) {
                    final String envValue = env.getProperty(key);
                    String env2Val = System.getProperty(key);

                    String source = propertySource.getName().contains("file:") ? "FILE" : "JAR";

                    if (envValue.equals(env2Val)) {
                        source = "ENV";
                    }

                    mapToLog.putIfAbsent(key, source);               
                }
            }
        }
    }
    return mapToLog;
}

我的示例输出描述了属性名称、值及其来源。我的财产价值描述了它们的来源。:

myprop: fooFromJar from JAR
aPropFromFile: fromExternalConfFile from FILE
mypropEnv: here from vm arg from ENV
  • ENV 表示我已经通过 -D 给了 JVM。
  • JAR 表示它来自 JAR 内的 application.properties
  • FILE 表示它来自 JAR 之外的 application.properties

0
投票

如果您认为 Actuator /env 端点存在安全风险,可以在 Baeldung's Log Properties in a Spring Boot (Maciej Główka) 中找到替代选项。 它包括使用以下代码实现

ContextRefreshedEvent
的 EventListener:

env.getPropertySources()
    .stream()
    .filter(ps -> ps instanceof MapPropertySource)
    .map(ps -> ((MapPropertySource) ps).getSource().keySet())
    .flatMap(Collection::stream)
    .distinct()
    .sorted()
    .forEach(key -> LOGGER.info("{}={}", key, env.getProperty(key)));

您还可以在 PropertySource 实现或自定义项目的键前缀上应用任何感兴趣的过滤。

© www.soinside.com 2019 - 2024. All rights reserved.