前言

  Spring Cloud Config为分布式系统中的外部化配置提供了服务器端和客户端支持。有了配置服务器,您就有了一个中心位置来管理跨所有环境的应用程序的外部属性。本文记录实现一个配置中心、客户端获取配置参数、refresh手动刷新

  官方文档:https://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.html

  帮助文档:https://spring.io/guides/gs/centralized-configuration/

  Config Server

  首先我们基于之前的代码,在springCloud工程下面新建一个Config Server,是一个springboot项目,并且在Eureka上面注册服务(还不会服务注册与发现的,请戳:SpringCloud系列——Eureka 服务注册与发现),本例使用的是GitHub

  maven引jar

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

  登录GitHub,新建一个public仓库:config-server,并且添加测试项目对应的配置文件:myspringboot-dev.properties,并设置几个值

  配置文件

server.port=
spring.application.name=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:/eureka/
#健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true
# 续约更新时间间隔(默认30秒)
eureka.instance.lease-renewal-interval-in-seconds=
# 续约到期时间(默认90秒)
eureka.instance.lease-expiration-duration-in-seconds= #连接GitHub
spring.cloud.config.server.git.uri=https://github.com/huanzi-qch/config-server.git
spring.cloud.config.server.git.search-paths=config-server
spring.cloud.config.label=master
spring.cloud.config.server.git.username=******
spring.cloud.config.server.git.password=******

  启动类加入注解@EnableConfigServer

@EnableConfigServer
@EnableEurekaClient
@SpringBootApplication
public class ConfigServerApplication { public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}

  启动项目,访问http://localhost:1112/myspringboot-dev.properties/,发现有中文乱码

  注:仓库中的配置文件会被转换成web接口,访问规则:

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

  解决中文乱码,参考:https://blog.csdn.net/sinat_38843093/article/details/79960777

  新建自定义解析器MyPropertiesHandler,继承PropertiesPropertySourceLoader,重写方法

/**
* 解决中文乱码问题
* 参考:https://blog.csdn.net/sinat_38843093/article/details/79960777
*/
public class MyPropertiesHandler extends PropertiesPropertySourceLoader { @Override
public String[] getFileExtensions() {
return new String[]{"properties", "xml"};
} @Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
ArrayList<PropertySource<?>> list = new ArrayList<>();
Properties properties = getProperties(resource);
if (!properties.isEmpty()) {
list.add(new PropertiesPropertySource(name, properties));
}
return list;
} private Properties getProperties(Resource resource) throws IOException {
Properties properties = new Properties();
InputStream inputStream = resource.getInputStream();
properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
inputStream.close();
return properties;
}
}

  resources文件夹下面新建META-INF文件夹,在里面创建spring.factories文件,指定使用我们自定义的解析器

org.springframework.boot.env.PropertySourceLoader=cn.huanzi.qch.config.configserver.MyPropertiesHandler

  重新启动项目,在自定义解析器后进行断点调试,发现解析的时候中文乱码问题得以解决,但响应回去还是乱码

  解决http响应中文乱码问题

  配置文件添加

#解决http响应数据中文乱码问题
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-

  最终效果

  我们去GitHub修改配置中心的值,看下config server能不能实时获取最新数据

  改完后刷新http://localhost:1112/myspringboot-dev.properties/,配置中心可以实时获取最新数据

  Config Client

  客户端我们直接用之前的项目:myspringboot,这里就当做一个在Eureka上注册了的普通springboot项目

  maven引入jar

        <!-- config-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

  application.properties

#设置服务端口
server.port=
spring.application.name=myspringboot #eureka
eureka.client.serviceUrl.defaultZone=http://localhost:/eureka/
#健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true
# 续约更新时间间隔(默认30秒)
eureka.instance.lease-renewal-interval-in-seconds=
# 续约到期时间(默认90秒)
eureka.instance.lease-expiration-duration-in-seconds=
#超时时间
feign.httpclient.connection-timeout=

  使用优先级更高的bootstrap.properties进行config的配置,因为

#关闭spring cloud config,spring cloud默认要从config中读取配置,通过该配置,只从本地application.properties中读取配置
#spring.cloud.config.enabled=false #配置文件名(当应用名跟配置文件相同时可以不用配置)
spring.cloud.config.name=myspringboot
# dev 开发环境配置文件 | test 测试环境 | pro 正式环境
spring.cloud.config.profile=dev
# 远程仓库的分支
spring.cloud.config.label=master #指定配置中心名称(如果使用eureka可以这样配置)
#spring.cloud.config.discovery.service-id=config-server
#启用发现服务功能
#spring.cloud.config.discovery.enabled=true #配置服务中心地址(如果不使用eureka可以直接配置url路径)
spring.cloud.config.uri=http://localhost:/

  如果使用从eureka获取配置中心实例,则要在指定服务之前进行注册配置,否则会报错,因为你还没在Eureka注册就去Eureka查找配置中心,如:

#设置服务端口
server.port=
spring.application.name=myspringboot #eureka
eureka.client.serviceUrl.defaultZone=http://localhost:/eureka/
#健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true
# 续约更新时间间隔(默认30秒)
eureka.instance.lease-renewal-interval-in-seconds=
# 续约到期时间(默认90秒)
eureka.instance.lease-expiration-duration-in-seconds=
#超时时间
feign.httpclient.connection-timeout= #关闭spring cloud config,spring cloud默认要从config中读取配置,通过该配置,只从本地application.properties中读取配置
#spring.cloud.config.enabled=false #配置文件名(当应用名跟配置文件相同时可以不用配置)
spring.cloud.config.name=myspringboot
# dev 开发环境配置文件 | test 测试环境 | pro 正式环境
spring.cloud.config.profile=dev
# 远程仓库的分支
spring.cloud.config.label=master #指定配置中心名称(如果使用eureka可以这样配置)
spring.cloud.config.discovery.service-id=config-server
#启用发现服务功能
spring.cloud.config.discovery.enabled=true #配置服务中心地址(如果不使用eureka可以直接配置url路径)
#spring.cloud.config.uri=http://localhost:1112/

  测试

  我们直接在启动类进行测试

@EnableEurekaClient
@SpringBootApplication
@RestController
public class MyspringbootApplication{ public static void main(String[] args) {
SpringApplication.run(MyspringbootApplication.class, args);
} @Value("${huanzi.qch.config.server.username}")
private String username; /**
* 访问首页
*/
@GetMapping("/index")
public String index(){
return "hello springboot!username:" + username;
} }

  查看启动日志,客户端已经发现了配置中心,并且从配置中心发现了myspringboot配置文件

  访问http://localhost:10087/index,值已经取到了

  其实客户端(Config Client)也是可以读取服务端(Config Server)配置文件里面的值,例如:

  客户端(Config Client)是可以读取到这个值的,由此可见,是客户端是读取了服务端的数据,而服务端负责实时获取GitHub上面的数据

  refresh手动刷新

  我们已经在客户端取到了配置中心的值,但当我们修改GitHub上面的值时,服务端(Config Server)能实时获取最新的值,但客户端(Config Client)读的是缓存,无法实时获取最新值

  spring已经为我们解决了这个问题,那就是客户端使用post去触发refresh,获取最新数据,需要依赖spring-boot-starter-actuator

        <!-- actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

  对应的controller类加上@RefreshScope

@RefreshScope
@EnableEurekaClient
@SpringBootApplication
@RestController
public class MyspringbootApplication{ public static void main(String[] args) {
SpringApplication.run(MyspringbootApplication.class, args);
} @Value("${huanzi.qch.config.server.username}")
private String username; /**
* 访问首页
*/
@GetMapping("/index")
public String index(){
return "hello springboot!username:" + username;
} }

  启动后查看日志发现,actuator有个基础路径/actuator,同时还暴露了两个终端(不知道是哪两个端点...)

  但是当我们post访问http://localhost:10087/actuator/refresh时,报404,这是什么回事?

  注:这里插一句话:从网上找了个js的ajax(要注意content-type的类型)

var Ajax={
get: function(url, fn) {
// XMLHttpRequest对象用于在后台与服务器交换数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
// readyState == 4说明请求已完成
if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
// 从服务器获得数据
fn.call(this, xhr.responseText);
}
};
xhr.send();
},
// datat应为'a=a1&b=b1'这种字符串格式,在jq里如果data为对象会自动将对象转成这种字符串格式
post: function (url, data, fn) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
// 添加http头,发送信息至服务器时内容编码类型
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
}
}
Ajax.post("http://localhost:10087/actuator/refresh",null,function(data){console.log(data)})

  经过层层查找,最后在帮助文档发现:默认情况下,自Spring Boot 2.0以来,默认情况下不会公开Actuator端点,需要手动暴露端点

  配置文件暴露端点

#只暴露refresh,当然也可以暴露所有:=*
management.endpoints.web.exposure.include=refresh

  重启客户端,我们将GitHub配置文件改回:huanzi.qch.config.server.username: 张三

  访问测试接口,还是张三1

  post调用refresh

  刷新,数据更新

  总结

  这里总结一下遇到的坑:

  调用refresh报404的时候,百度查找都是说默认安全拦截,配置关闭:management.security.enabled=false,配置上去的时候发现报错,波浪线,被弃用了,

  最后还是靠Google,在知乎(https://zhuanlan.zhihu.com/p/34784934)上面找到了答案

  

  并且吐槽吐槽百度:

  同样的关键字,Google搜出来的第一个就能解决问题

  而垃圾百度,没一个可以...

  代码开源

  代码已经开源、托管到我的GitHub、码云:

  GitHub:https://github.com/huanzi-qch/springCloud

  码云:https://gitee.com/huanzi-qch/springCloud

SpringCloud系列——Config 配置中心的更多相关文章

  1. springCloud系列 Config配置中心

    1.config服务的部署 2.yum文件的格式 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 3.热部署 4.配 ...

  2. SpringCloud之Config配置中心+BUS消息总线原理及其配置

    一.配置中心作用 在常规的开发中,每个微服务都包含代码和配置.其配置包含服务配置.各类开关和业务配置.如果系统结构中的微服务节点较少,那么常规的代码+配置的开发方式足以解决问题.当系统逐步迭代,其微服 ...

  3. springcloud之config配置中心-Finchley.SR2版

    本篇和大家分享的是springcloud-config配置中心搭建,写到这里突然想起自己曾今开源过基于Redis发布订阅编写的一个配置中心,刚看了git星数有点少哈哈,这里顺势发个连接欢迎大侠们点赞: ...

  4. SpringCloud系列之配置中心(Config)使用说明

    大家好,最近公司新项目采用SpingCloud全家桶进行开发,原先对SpringCloud仅仅只是停留在了解的初级层面,此次借助新项目的契机可以深入实践下SpringCloud,甚是Happy.大学毕 ...

  5. Spring-Cloud之Config配置中心-7

    一.我们前面基本上都是讲解的Spring Cloud Netflix的组件,下面我们会重点说Spring Cloud Config分布式配置中心.为什么需要这个组件来管理配置呢?在分布式应用开发过程中 ...

  6. SpringBoot(三) - Ribbon客户端负载均衡,Zuul网关,Config配置中心

    1.Ribbon客户端负载均衡 1.1 依赖 1.2 配置信息 # feign默认加载了ribbon负载均衡,默认负载均衡机制是:轮询 # 负载均衡机制是添加在消费端(客户端)的,如果改为随机,指定服 ...

  7. SpringCloud学习系列之五-----配置中心(Config)和消息总线(Bus)完美使用版

    前言 在上篇中介绍了SpringCloud Config的使用,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的分布式配置中心( ...

  8. SpringCloud学习系列之四-----配置中心(Config)使用详解

    前言 本篇主要介绍的是SpringCloud中的分布式配置中心(SpringCloud Config)的相关使用教程. SpringCloud Config Config 介绍 Spring Clou ...

  9. 跟我学SpringCloud | 第七篇:Spring Cloud Config 配置中心高可用和refresh

    SpringCloud系列教程 | 第七篇:Spring Cloud Config 配置中心高可用和refresh Springboot: 2.1.6.RELEASE SpringCloud: Gre ...

随机推荐

  1. TypeScript 实现任务队列

    业务中经常会有一些批量操作的任务,比如使用 JavaScript 预加载一组图片,批量上传一些资源.如果这些任务一次性启动,势必会消耗很多资源和带宽.理想的做法应该对这些任务进行限制,比如一次只跑几个 ...

  2. PostCSS 基本用法

    1.postcss相关网站 https://www.postcss.com.cn/ https://www.ibm.com/developerworks/cn/web/1604-postcss-css ...

  3. 再遇angular(angular4项目实战指南)

    这两天看了看angular4的文档,发现他和angular1.X的差别真的是太大了,官方给出的那个管理英雄的Demo是一个非常好的入门项目,这里给出一个管理个人计划的小项目,从头至尾一步一步讲解如何去 ...

  4. C#判断字符串是不是英文或数字

    利用正则.   u4e00-u9fa5; //中文  ^[A-Za-z]+$  //英文字母 //截取冲击式样形状 public string SubStringForXingZhuang(strin ...

  5. 简单Java类 全网最详细讲解 !!!

    最近学习java非常吃力,学习的进度很快,由于基础没打牢固,整体上项目理解很吃力,偶尔会遇到一些基本的概念,都会阻碍整体的理解.最近也看了不少的视频讲解,听得很迷,最后搞得很乱,没有明确的学习目标,今 ...

  6. Python猜数小游戏

    使用random变量随机生成一个1到100之间的数 采集用户所输入的数字,如果输入的不符合要求会让用户重新输入. 输入符合要求,游戏开始.如果数字大于随机数,输出数字太大:如果小于随机数,输出数字太小 ...

  7. 删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录

    delete from Resource where Title in (select Title from Resource group by Title having count(Title) & ...

  8. Linux 初始环境配置 以及避坑 (详细)

    没事儿喜欢自己装个虚拟机捣鼓捣鼓,经过几次装一些Linux 经验, 有时候  电脑了 .想重新系统了,又要重新去配置环境, 有时候又要去查很多很多命令 . 记录分享下Linux 下配置开发环境以及桌面 ...

  9. 我的Windows日常——鼠标无法进行拖拽的解决方法

    方法1: 鼠标右键单击任务栏 选择属性,进入任务栏和开始菜单属性 点击「开始」菜单  进入分页,单击自定义 找到并勾选启用上下文菜单和拖放 一路确定.... --------------------- ...

  10. WEB框架-Django框架学习-关联管理器(RelatedManager)

    一.class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况: 1.一对多 ForeignKey关系的“另一边” ...