[Java] Spring项目通过git统一管理配置文件
技术栈:springboot2.0,docker,k8s
在做java的spring项目开发,少不了涉及到不同环境的配置问题。一般情况下,生产的配置都不会直接放到项目里面的,这就涉及如何管理好生产配置的问题。
本文介绍通过git来统一管理项目的配置文件(特别是使用到微服务),以方便日常开发部署
步骤一 源码实现
首先,你得有一个所有微服务都用到的公共包
这里用到最关键的知识点就是Spring SPI。如对想深入了解,建议先google一下
源码: src/main/resources/META-INF/spring.factories
# Bootstrap Configuration org.springframework.cloud.bootstrap.BootstrapConfiguration=\ com.ppwang.lib.common.config.file.LibBusinessConfigBootstrapConfiguration
源码: src/main/java/com/ppwang/lib/common/config/file/LibBusinessConfigBootstrapConfiguration.java
package com.ppwang.lib.common.config.file; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * {@code LibBusinessConfigBootstrapConfiguration} 描述内容 * */ @Configuration("com.ppwang.lib.common.config.file.LibBusinessConfigBootstrapConfiguration") @ConditionalOnProperty( prefix = "pp-lib-business.common.config.file", value = "libBusinessConfigBootstrapConfiguration.enabled", havingValue = "true", matchIfMissing = true ) public class LibBusinessConfigBootstrapConfiguration { @Bean public LibBusinessPropertySourceLocator libBusinessPropertySourceLocator() { return new LibBusinessPropertySourceLocator(); } }
源码: src/main/java/com/ppwang/lib/common/config/file/LibBusinessPropertySourceLocator.java
package com.ppwang.lib.common.config.file; import com.ppwang.lib.common.util.LogUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.bootstrap.config.PropertySourceLocator; import org.springframework.core.annotation.Order; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; /** * {@code LibBusinessPropertySourceLocator} 描述内容 * */ @Order(-1) @Slf4j public class LibBusinessPropertySourceLocator implements PropertySourceLocator { @Override public PropertySource<?> locate(Environment environment) { if (!(environment instanceof ConfigurableEnvironment)) { return null; } else { ConfigurableEnvironment env = (ConfigurableEnvironment)environment; String configFolderPath = env.getProperty( "pp-lib-business.common.config.file.libBusinessPropertySourceLocator.pea-config-center-java", String.format("/opt/pea-config-center-java/%s", env.getProperty("spring.application.name")) ); CompositePropertySource composite = new CompositePropertySource("pea-config-center-java"); try { Files .list(Paths.get(configFolderPath)) .filter(Files::isRegularFile) .forEach(file -> assembleCompositePropertySource(composite, file)); } catch (Exception e) { log.info("{}. Lib business config folder does not exist.", LogUtils.fileInfoStr()); return null; } return composite; } } private void assembleCompositePropertySource(CompositePropertySource composite, Path configFolderFilePath) { try { File configFolderFile = configFolderFilePath.toFile(); LibBusinessPropertySource libBusinessPropertySource = new LibBusinessPropertySource(configFolderFile.getName(), configFolderFile); libBusinessPropertySource.init(); composite.addPropertySource(libBusinessPropertySource); } catch (Exception e) { log.info("{}. {}, Lib business config folder file load failed.", LogUtils.fileInfoStr(), configFolderFilePath.getFileName(), e); } } }
源码: src/main/java/com/ppwang/lib/common/config/file/LibBusinessPropertySource.java
package com.ppwang.lib.common.config.file; import com.ppwang.lib.common.util.LogUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.cloud.consul.config.encrypt.EncryptConfig; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.FileSystemResource; import org.springframework.util.CollectionUtils; import java.io.File; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * {@code LibBusinessPropertySource} 描述内容 * */ @Slf4j public class LibBusinessPropertySource extends EnumerablePropertySource<File> { private final Map<String, Object> properties = new LinkedHashMap(); public LibBusinessPropertySource(String name, File source) { super(name, source); } public void init() { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); try { List<PropertySource<?>> loads = loader.load("pea-config-center-java", new FileSystemResource(this.source)); if (CollectionUtils.isEmpty(loads)) { return; } PropertySource<?> propertySource = loads.get(0); Map<String, Object> sourceMap = (Map<String, Object>) propertySource.getSource(); Iterator<Map.Entry<String, Object>> iterator = sourceMap.entrySet().iterator(); if (EncryptConfig.getEnabled()) { while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); if (EncryptConfig.needDecrypt(entry.getValue())) { if (log.isTraceEnabled()) { log.debug( "[pea-config-center-java] Need Decrypt {} > {}: {}", entry.getKey(), entry.getKey(), entry.getValue()); } String decryptedValue = EncryptConfig.getProvider().decrypt( EncryptConfig.realContent(entry.getValue()), EncryptConfig.getPassword() ); this.properties.put(entry.getKey(), decryptedValue); } else { this.properties.put(entry.getKey(), entry.getValue()); } } } else { while(iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); this.properties.put(entry.getKey(), entry.getValue()); } } } catch (Exception e) { log.info( "{}. Failed to load pea-config-center-java file. {}, {}", LogUtils.fileInfoStr(), this.source.getPath(), this.source.getName(), e ); } } @Override public String[] getPropertyNames() { Set<String> strings = this.properties.keySet(); return strings.toArray(new String[0]); } @Override public Object getProperty(String name) { return this.properties.get(name); } }
步骤二,运维层面
我们的配置通过git管理之后,在打包docker镜像的时候,可从git上拉取配置,然后复制到镜像里约定好的目录下。比如,这里是/opt/pea-config-center-java/${spring.application.name}。注意这里${spring.application.name}指的是项目名
其他细节就不用多说了,按以上操作就可实现通过git来统一管理配置项
Have fun with java & spring!