我们的运维人员希望在应用程序启动时将 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]
]
}
如何解决此问题以便加载和打印所有属性?
没有内置机制,这实际上取决于您所说的“所有属性”的含义。您只想要you编写的实际键还是想要所有属性(包括默认值)。
对于前者,您可以轻松监听
ApplicationEnvironmentPreparedEvent
并记录您感兴趣的属性源。对于后者,/configprops
确实是一个更好/完整的输出。
这仅记录配置的属性 *.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
如果您认为 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 实现或自定义项目的键前缀上应用任何感兴趣的过滤。