(一)基础知识学习
参见Spring Cloud 配置客户端技术基础
(二)客户单端配置
主要涉及以下知识:
- Bootstrap 配置文件
- 调整 Bootstrap 配置文件路径
- 覆盖远程配置文件属性
- 自定义 Bootstrap 配置
- 自定义 Bootstrap 配置属性源
1、Bootstrap 配置文件
注意事项一:
加载 Bootstrap 配置文件的监听器为:BootstrapApplicationListener
注意事项二:
String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
这段代码的意思是,若未配置spring.cloud.bootstrap.name
属性,则读取bootstrap.properties
或bootstrap.yml
为Bootstrap 配置文件;若配置spring.cloud.bootstrap.name=test
,则读取test.properties
或test.yml
为Bootstrap 配置文件。
注意事三:
#application.properties
#通过调整 spring.cloud.bootstrap.enabled = false,尝试关闭 bootstrap 上下文
#实际测试结果,没有效果
spring.cloud.bootstrap.enabled = false
原因解析:BootstrapApplicationListener 加载实际早于 ConfigFileApplicationListener(加载 application.yml 的监听器):
- ConfigFileApplicationListener 的 Ordered.HIGHEST_PRECEDENCE +10(第十一位加载)
- BootstrapApplicationListener 的 Ordered.HIGHEST_PRECEDENCE + 5(第六位加载)
要想 spring.cloud.bootstrap.enabled = false
生效,解决办法之一,就是在JVM的启动参数里设置--spring.cloud.bootstrap.enabled = false
(这里的启动优先级比这两个更高)
注意事项四:
JVM启动参数的加载逻辑:
SpringApplication.configurePropertySources()
2、调整 Bootstrap 配置文件路径
通过前面可知,BootstrapApplicationListener 加载实际早于 ConfigFileApplicationListener(加载 application.yml 的监听器),所以想在application.yml中调整 Bootstrap 配置文件路径是无法实现的,仍然需要在JVM的启动参数里设置,设置项为--spring.cloud.bootstrap.location = config
。调整 Bootstrap 配置文件路径之后,配置文件的加载顺序是什么,这里用一个Demo展示:
在不同的配置文件中设置 application 的名字:
application.yml
spring.application.name = spring-cloud-application
bootstrap.yml
spring.application.name = spring-cloud-bootstrap
spring-cloud.yml
spring.application.name = spring-cloud
config/spring-cloud.yml
spring.application.name = spring-cloud-config
设置JVM启动参数:
//设置 bootstrap 配置文件名为 spring-cloud
--spring.cloud.bootstrap.name = spring-cloud
//设置 Bootstrap 配置文件路径classpath:/config
--spring.cloud.bootstrap.location = config
加载效果:
applicationConfig: [classpath:/application.yml] : {
spring.application.name = spring-cloud-application
}
......
applicationConfig: [classpath:config/spring-cloud.yml] : {
spring.application.name = spring-cloud-application
}
applicationConfig: [classpath:/spring-cloud.yml] : {
spring.application.name = spring-cloud-application
}
备注:spring.application.name 最终读取的是 application.yml 中配置的项,而读取文件的顺序是:
先读 application.yml:不用说,Spring Boot上下文肯定会读到
再读:config/spring-cloud.yml:也不用说,JVM参数设置的bootstrap 配置文件名和路径
最后读spring-cloud.yml:这里就比较奇怪了,为什么还读 resources 路径下的spring-cloud.yml??
3、覆盖远程配置文件属性
默认情况,Spring Cloud 是容许覆盖的:spring.cloud.config.allowOverride=true
。可以通过JVM启动参数,调整该属性为false(PS:但是这在本地无法生效,本地依然可以覆盖!!!这个仅适用于远程配置,远程无法再覆盖属性):
--spring.cloud.config.allowOverride=false
4、自定义 Bootstrap 配置
(1)创建META-INF/spring.factories
文件,类似于Spring Boot 自定义 Starter;
(2)自定义Bootstrap 配置Configuration
package org.pc.bootstrap;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import java.util.HashMap;
import java.util.Map;
/**
*自定义 Bootstrap 配置 Bean
* @author 咸鱼
* @date 2018/10/30 19:22
*/
public class MyConfiguration implements ApplicationContextInitializer {
public void initialize(ConfigurableApplicationContext applicationContext) {
//从 ConfigurableApplicationContext 获取 ConfigurableEnvironment 实例
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//获取 PropertySources
MutablePropertySources propertySources = environment.getPropertySources();
//定义一个新的 PropertySource
PropertySource propertySource = createPropertySource();
//将新建的 PropertySource 增加到集合中,并且放置在首位
propertySources.addFirst(propertySource);
}
private PropertySource createPropertySource() {
Map<String, Object> source = new HashMap<>();
source.put("name", "咸鱼");
PropertySource propertySource = new MapPropertySource("my-property-source", source);
return propertySource;
}
}
(2)配置META-INF/spring.factories
文件,关联 Key org.springframework.cloud.bootstrap.BootstrapConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.pc.bootstrap.MyConfiguration
通过以上步骤,就可以将自定义的变量放到Bootstrap 上下文中,可以通过http://localhost:8081/actuator/env
查看新增的属性:
{
"name": "my-property-source",
"properties": {
"name": {
"value": "咸鱼"
}
}
}
5、自定义 Bootstrap 配置属性源
(1)自定义实现 PropertySourceLocator 接口
package org.pc.bootstrap;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.*;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义 {@link PropertySourceLocator} 实现
* @author 咸鱼
* @date 2018/10/30 19:42
*/
public class MyPropertySourceLocator implements PropertySourceLocator {
public PropertySource<?> locate(Environment environment) {
//判断是否是 ConfigurableEnvironment 类型
if (environment instanceof ConfigurableEnvironment){
//若是,强转
ConfigurableEnvironment configurableEnvironment = ConfigurableEnvironment.class.cast(environment);
//获取 PropertySources
MutablePropertySources propertySources = configurableEnvironment.getPropertySources();
//将新建的 PropertySource 增加到集合中,并且放置在首位
propertySources.addFirst(createPropertySource());
}
return null;
}
private PropertySource createPropertySource() {
Map<String, Object> source = new HashMap<>();
source.put("nickName", "咸鱼昵称");
//设置名称 来源
PropertySource propertySource = new MapPropertySource("my-property-source-1", source);
return propertySource;
}
}
(2)配置META-INF/spring.factories
文件,关联 Key org.springframework.cloud.bootstrap.BootstrapConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.pc.bootstrap.MyPropertySourceLocator
通过以上步骤,就可以将自定义的变量放到Bootstrap 上下文中,可以通过http://localhost:8081/actuator/env
查看新增的属性:
{
"name": "my-property-source-1",
"properties": {
"nickName": {
"value": "咸鱼昵称"
}
}
}
(三)客户端和服务端联合配置
参见三、Spring cloud之服务器配置和客户端配置