本站公告: PUI正式上线,欢迎体验。

spring Cloud 微服务学习之基于数据库的ConfigServer

框架积累 Mignon 13459浏览 1评论

上一篇《 spring Cloud 微服务学习之ConfigServer》我们说了最基本的基于git服务器的config server,有一些朋友问我基于数据库的config server怎么弄,今天我们就讲解基于数据库的config server.

基于git(默认)的config server项目中我们在pom.xml导入:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

基于mysql数据库pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

基于数据库(mongodb)pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

基于数据库(H2)pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.191</version>
</dependency>

其中H2和Mysql是差不多只是jdbc的配置不同,我们下面主要讲解怎么搭建基于mysql的config server

ConfigApplication.java

@EnableConfigServer
@SpringBootApplication
public class ConfigApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.web(true).sources(ConfigApplication.class);
    }
}

我们先从Config Server源码来了解,spring cloud是怎么做的。

EnableConfigServer的源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({EnvironmentRepositoryConfiguration.class, ResourceRepositoryConfiguration.class, ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class})
public @interface EnableConfigServer {
}

我们可以看见EnableConfigServer的注释中有一个导入的配置

@Import({EnvironmentRepositoryConfiguration.class, ResourceRepositoryConfiguration.class, ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class})

而配置资源的configuration是EnvironmentRepositoryConfiguration源码如下:

@Configuration
@ConditionalOnMissingBean({EnvironmentRepository.class})
@EnableConfigurationProperties({ConfigServerProperties.class})
public class EnvironmentRepositoryConfiguration {
    public EnvironmentRepositoryConfiguration() {
    }

    @Bean
    @ConditionalOnProperty(
        value = {"spring.cloud.config.server.health.enabled"},
        matchIfMissing = true
    )
    public ConfigServerHealthIndicator configServerHealthIndicator(EnvironmentRepository repository) {
        return new ConfigServerHealthIndicator(repository);
    }

    @Configuration
    @Profile({"subversion"})
    protected static class SvnRepositoryConfiguration {
        @Autowired
        private ConfigurableEnvironment environment;
        @Autowired
        private ConfigServerProperties server;

        protected SvnRepositoryConfiguration() {
        }

        @Bean
        public EnvironmentRepository environmentRepository() {
            SvnKitEnvironmentRepository repository = new SvnKitEnvironmentRepository(this.environment);
            if(this.server.getDefaultLabel() != null) {
                repository.setDefaultLabel(this.server.getDefaultLabel());
            }

            return repository;
        }
    }

    @Configuration
    @ConditionalOnMissingBean({EnvironmentRepository.class})
    protected static class GitRepositoryConfiguration {
        @Autowired
        private ConfigurableEnvironment environment;
        @Autowired
        private ConfigServerProperties server;

        protected GitRepositoryConfiguration() {
        }

        @Bean
        public EnvironmentRepository environmentRepository() {
            MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment);
            if(this.server.getDefaultLabel() != null) {
                repository.setDefaultLabel(this.server.getDefaultLabel());
            }

            return repository;
        }
    }

    @Configuration
    @Profile({"native"})
    protected static class NativeRepositoryConfiguration {
        @Autowired
        private ConfigurableEnvironment environment;

        protected NativeRepositoryConfiguration() {
        }

        @Bean
        public EnvironmentRepository environmentRepository() {
            return new NativeEnvironmentRepository(this.environment);
        }
    }
}

可以通过:spring.profiles.active=xxx来激活相应的环境配置,其中

@Configuration
@ConditionalOnMissingBean({EnvironmentRepository.class})
protected static class GitRepositoryConfiguration {
    @Autowired
    private ConfigurableEnvironment environment;
    @Autowired
    private ConfigServerProperties server;

    protected GitRepositoryConfiguration() {
    }

    @Bean
    public EnvironmentRepository environmentRepository() {
        MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment);
        if(this.server.getDefaultLabel() != null) {
            repository.setDefaultLabel(this.server.getDefaultLabel());
        }

        return repository;
    }
}

为当前默认配置资源服务

而我们需要做的就是将默认的GitRepositoryConfiguration替换为基于数据库的RepositoryConfiguration。

下面我们来创建自己的RepositoryConfiguration,暂时定为:DatabasesRepositoryConfiguration.

DatabasesRepositoryConfiguration.java

@Configuration
@ConditionalOnMissingBean({EnvironmentRepository.class})
public class DatabasesRepositoryConfiguration {


}

新建配置Entity:ConfigRepository.java用来存储应用名称、应用模块、应用环境(测试、生产)、应用版本来获取该程序的配置信息。

@Entity
@Table
public class ConfigRepository {
    @Id
    @GeneratedValue
    private Long configKey;
    private String application;   //应用名称
    private String profile;       //应用模块
    private String label;         //应用环境
    private String version;       //应用版本
    @ManyToMany
    @JoinTable(name = "config_properties_repository")
    private List<ConfigProperties> configPropertiesList = new ArrayList<>();
    ...
    ...
}

新建entity:ConfigProperties.java统一的配置信息,这里我为了达到配置重用的目的才创建ConfigProperties,这样我们只需要对ConfigRepository进行关联便可以得到灵活程序配置信息。

@Entity
@Table
public class ConfigProperties {
    @Id
    @GeneratedValue
    private Long propertiesKey;

    private String propertiesName;
    @Lob
    @Column
    @Type(type = "com.sixtykb.type.JsonType")
    private Map<String, String> content = new HashMap<>();
    ...
}

创建ConfigDbRepository.java,基于spring data jpa的查询dao。

@Repository
public interface ConfigDbRepository extends JpaRepository<ConfigRepository, Long> {
    ConfigRepository findFirstByApplicationAndProfileAndLabel(String application, String profile, String label);
}

创建config服务:ConfigRepositoryService.java,配置信息查询服务。

@Service
public class ConfigRepositoryService {
    @Autowired
    private ConfigDbRepository configDbRepository;

    public ConfigRepository findByApplicationAndProfileAndLabel(String application, String profile, String label) {
        return configDbRepository.findFirstByApplicationAndProfileAndLabel(application, profile, label);
    }
}

创建配置服务的核心服务:DatabasesEnvironmentRepository.java,生成该程序的配置对象。

public class DatabasesEnvironmentRepository implements EnvironmentRepository {

    @Autowired
    private ConfigRepositoryService configRepositoryService;

    @Override
    public Environment findOne(String application, String profile, String label) {
        if (StringUtils.isEmpty(application) || StringUtils.isEmpty(profile))
            return null;
        ConfigRepository configRepositories = configRepositoryService.findByApplicationAndProfileAndLabel(application, profile, label);
        if (configRepositories != null) {
            Environment environment = new Environment(application, StringUtils.commaDelimitedListToStringArray(profile), label, configRepositories.getVersion());
            for (ConfigProperties configProperties : configRepositories.getConfigPropertiesList()) {
                environment.add(new PropertySource(configProperties.getPropertiesName(), configProperties.getContent()));
            }
            return environment;
        }
        return new Environment(application, profile);
    }
}

通过application、profile、label查询配置文件信息。

现在我们把DatabasesRepositoryConfiguration.java的代码补全:

@Configuration
@ConditionalOnMissingBean(EnvironmentRepository.class)
@ConditionalOnProperty("spring.cloud.config.server.databases")
public class DatabasesRepositoryConfiguration {

    @Autowired
    private ConfigurableEnvironment environment;

    @Bean
    public SearchPathLocator searchPathLocator() {
        return new NativeEnvironmentRepository(environment);
    }

    @Bean
    @Primary
    public EnvironmentRepository openEnvironmentRepository() {
        return new DatabasesEnvironmentRepository();
    }
}

这里

@ConditionalOnProperty("spring.cloud.config.server.databases")

的意思是可以通过配置进行动态激活,也就是可以通过在bootstrap.properties配置文件中指定:

spring.cloud.config.server.databases=true

来激活基于数据库的config服务。

由于工作有些忙,很长时间没有写博客了,下次我们来讲解spring cloud 服务注册。

转载请注明:码农博客 » spring Cloud 微服务学习之基于数据库的ConfigServer

游客
发表我的评论 换个身份
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  • 验证码 (必填)点击刷新验证码

网友最新评论 (1)

  1. 访客
    谢谢分享 提供了思路
    尼莫 9个月前 (12-28)回复