天天看点

【Spring Cloud总结】33.编写Config Client

接上篇《32.编写Config Server》  Spring Cloud版本为Finchley.SR2版

上一篇我们搭建了一个私有远端仓库,并编写了Spring Cloud Config的Server服务端,连接远端仓库并成功提供了配置服务端点。本篇我们来编写Spring Cloud Config的Client客户端。

本部分官方文档:https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html#_client_side_usage_2

注:好像Finchley.SR2的文档已经挂了,最新的是Finchley.SR4的文档。

我们依旧来回顾Spring Cloud Config的架构图:

【Spring Cloud总结】33.编写Config Client

上一篇我们编写的Config Server服务端可以从后端存储中(上图为Git)拉取配置参数、属性,然后对外提供获取相应环境(dev开发、stage预发布、prod生产)配置的Restful服务。此时我们的Config Client客户端就可以通过Config Server提供的服务获取相关配置。

下面我们就来动手编写一个Config Client客户端,对接我们上一篇编写的Config Server服务端。

一、新建Config Client客户端工程

在工作空间中新建一个名为“microserver-config-client”的Maven工程:

【Spring Cloud总结】33.编写Config Client
【Spring Cloud总结】33.编写Config Client

然后在POM文件中引入Spring Cloud的父工程、config-client的依赖,因为我们这个客户端需要使用SpringMVC,所以这里添加了web的依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>microserver-config-client</artifactId>
  <name>microserver-config-client</name>
  
  <parent>
        <groupId>com.microserver.cloud</groupId>
        <artifactId>microserver-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
  
  <dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
  
</project>
           

注意,这里为了便于版本统一管理,该工程的parent父工程和我们User、Movie工程一样,均依赖于microserver-spring-cloud工程(此父工程统一引入了spring-cloud-dependencies的Finchley.SR2版,这个在前面的章节已经讲过)。

父工程pom.xml的modules中别忘记加入这个新工程(microserver-config-client):

<modules>
    <module>microserver-provider-user</module>
    <module>microserver-consumer-movie</module>
    <module>microserver-discovery-eureka</module>
    <module>microserver-discovery-eureka-high-availability</module>
    <module>microserver-hystrix-dashboard</module>
    <module>microserver-hystrix-dashboard-turbine</module>
    <module>microserver-getaway-zuul</module>
    <module>microserver-file-upload</module>
    <module>microserver-sidecar</module>
    <module>microserver-config-server</module>
    <module>microserver-config-client</module>
</modules>
           

然后我们新建SpringBoot启动类:

package com.microserver.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConfigClientApplication {

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

}
           

然后在resource文件夹下创建application.yml,配置一下端口,以及拉取配置的后端存储的uri路径、应用名,以及Config Server的服务地址,以及需要从Config Server获取的配置版本信息:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
  cloud:
    config:
      uri: http://localhost:8090
      profile: dev
      label: master  #如果ConfigServer的后端存储是Git,默认就为master
           

然后我们创建一个Controller来编写一个服务,通过该服务获取Config Server的配置:

package com.microserver.cloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {
    
    @Value("${type}")
    private String profileType;
    
    @GetMapping("/profileType")
    private String getProfileType() {
        return this.profileType;
    }
} 
           

注:这里的${type},就是之前我们放在仓库里的默认dev配置文件的参数:

【Spring Cloud总结】33.编写Config Client

此时我们的客户端算是搭建完毕了,这样就能直接获取信息了吗?我们来试试。

二、Config Client的加载问题

先后启动microserver-config-server和microserver-config-client工程,我们可以看到microserver-config-client工程的控制台报错了:

【Spring Cloud总结】33.编写Config Client

下面的异常信息就是加载不了“${type}”的值,而具体原因是上面的“Fetching config from server at : http://localhost:8888”,但是我们的spring.cloud.config.uri不是配置的“http://localhost:8090”吗?我们来探讨一下原因。

首先我们需要了解一下Bootstrap Application Context,叫“启动上下文”(官方文档解释:https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html#_the_bootstrap_application_context),它是用来加载远端的ConfigServer的配置。启动的时候内置的bootstrap.yml配置文件,然后获取Config Server的配置,去连接Config Server,然后再去加载application.yml文件。而由于默认的bootstrap.yml配置文件中的spring.cloud.config.uri是“http://localhost:8888”,所以我们加载不出来。

此时我们在resource下新建一个名为bootstrap.yml的配置文件,在里面设置spring.cloud.config.uri:

spring:
  cloud:
    config:
      uri: http://localhost:8090
      profile: dev
      label: master  #如果ConfigServer的后端存储是Git,默认就为master
           

然后把原来在application.yml中的spring.cloud.config.uri配置删除:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
           

工程文件结构:

【Spring Cloud总结】33.编写Config Client

然后我们重启工程,发现控制台不再报错,然后我们访问"/profileType"服务,发现可以拿到数据:

【Spring Cloud总结】33.编写Config Client

我们在gitee仓库中存储的application-dev.yml中的内容即是:

type: dev

但这其实只是获取到了默认的dev配置文件,要知道Config Server获取参数的机制如下:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
           

这里的“application”前缀,即是我们的应用名“spring.application.name”,我们在本地仓库新建一个“microserver-config-client-dev.yml”文件,内容为“type: client-dev”:

【Spring Cloud总结】33.编写Config Client

然后上传到远端仓库:

【Spring Cloud总结】33.编写Config Client
【Spring Cloud总结】33.编写Config Client
【Spring Cloud总结】33.编写Config Client

此时重启服务,重新访问"/profileType"服务,发现可以拿到该应用名对应的配置文件的数据:

【Spring Cloud总结】33.编写Config Client

至此,我们的Config Client成功获取到配置仓库的对应信息。我们不同的应用可以根据不同的applicationName去远程仓库获取自己应用对应的配置内容。

二、相关问题

1、本地配置和远程配置冲突问题

上面我们在Controller中使用@Value("${type}")注解注入了type参数,这个type参数是远程仓库中的参数,那么此时如果我们在application.yml配置文件中,加一个本地的参数type会怎样呢:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
    
type: abcd
           

我们重启microserver-config-client工程,访问"/profileType"服务,看一下type的值:

【Spring Cloud总结】33.编写Config Client

发现还是以远端的type值为主,并没有被本地的同名参数值(abcd)覆盖。

这个机制也很好解释,因为系统先加载bootstrap.yml配置文件获取了配置值,然后注入到Controller的参数中,而我们的Controller加载完毕之后,是一个单例状态,注入的数据已经在这个单例类中,不会再次覆盖。后面我们再加载application.yml时,type已经被注入Controller中了。

2、spring.application.name与远端仓库文件的关系

如果应用没有设置spring.application.name应用名,或仓库没有找到对应的应用名的配置文件,则只会取到application-*.yml这种默认的配置文件,所以要确保工程的spring.application.name已配置,并且在远端仓库中托管有这种应用名前缀的配置文件。

参考:《51CTO学院Spring Cloud高级视频》

转载请注明出处:https://blog.csdn.net/acmman/article/details/104718599

继续阅读