Merge pull request #2349 from DanielLiu1123/support_spring_config_import
Support spring.config.importpull/2364/head
commit
14ecf7870b
@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>nacos-config-2.4.x-example</artifactId>
|
||||||
|
<name>Spring Cloud Starter Alibaba Nacos Config 2.4.x Example</name>
|
||||||
|
<description>Example demonstrating how to use nacos config in spring boot 2.4.x</description>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>${maven-deploy-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,105 @@
|
|||||||
|
# Nacos Config 2.4.x Example
|
||||||
|
|
||||||
|
## 项目说明
|
||||||
|
|
||||||
|
Spring Boot 2.4.0 版本开始默认不启动 bootstrap 容器
|
||||||
|
本项目演示如何在 Spring boot >= 2.4.0 版本不启用 bootstrap 容器情况下如何使用 nacos
|
||||||
|
|
||||||
|
[Nacos](https://github.com/alibaba/Nacos) 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
### 如何接入
|
||||||
|
|
||||||
|
1. 首先,修改 pom.xml 文件,引入 Nacos Config Starter
|
||||||
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
|
<!-- 不再需要 bootstrap 容器 -->
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
2. 在应用的 /src/main/resources/***application.yml*** 配置文件中配置 Nacos Config 元数据
|
||||||
|
```yaml
|
||||||
|
server:
|
||||||
|
port: 8888
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: nacos-config-import-example
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
config:
|
||||||
|
name: test.yml
|
||||||
|
file-extension: yml
|
||||||
|
# 2.4.0 新增配置 spring.config.import
|
||||||
|
config:
|
||||||
|
import:
|
||||||
|
- optional:nacos:localhost:8848
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 在 nacos 创建 test.yml
|
||||||
|
```yaml
|
||||||
|
configdata:
|
||||||
|
user:
|
||||||
|
age: 21
|
||||||
|
name: freeman
|
||||||
|
map:
|
||||||
|
hobbies:
|
||||||
|
- art
|
||||||
|
- programming
|
||||||
|
intro: Hello, I'm freeman
|
||||||
|
users:
|
||||||
|
- name: dad
|
||||||
|
age: 20
|
||||||
|
- name: mom
|
||||||
|
age: 18
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 完成上述操作后,应用会从 Nacos Config 中获取相应的配置,并添加在 Spring Environment 的 PropertySources 中
|
||||||
|
```java
|
||||||
|
// controller
|
||||||
|
@RestController
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserConfig userConfig;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String get() throws JsonProcessingException {
|
||||||
|
return new ObjectMapper().writeValueAsString(userConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigurationProperties
|
||||||
|
@ConfigurationProperties(prefix = "configdata.user")
|
||||||
|
public class UserConfig {
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
private Map<String, Object> map;
|
||||||
|
private List<User> users;
|
||||||
|
// getters and setters ...
|
||||||
|
|
||||||
|
public static class User {
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
// getters and setters ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
验证动态刷新
|
||||||
|
访问 http://localhost:8888
|
||||||
|
再从 nacos 修改配置, 再次访问即可验证动态配置生效
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.imports.examples;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.imports.examples.model.UserConfig;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableConfigurationProperties(UserConfig.class)
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2022 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.imports.examples.controller;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.imports.examples.model.UserConfig;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserConfig userConfig;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String get() throws JsonProcessingException {
|
||||||
|
return new ObjectMapper().writeValueAsString(userConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2022 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.imports.examples.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "configdata.user")
|
||||||
|
public class UserConfig {
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
private Map<String, Object> map;
|
||||||
|
private List<User> users;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(Integer age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getMap() {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMap(Map<String, Object> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsers(List<User> users) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class User {
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(Integer age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
server:
|
||||||
|
port: 8888
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: nacos-config-import-example
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
config:
|
||||||
|
group: DEFAULT_GROUP
|
||||||
|
server-addr: localhost:8848
|
||||||
|
config:
|
||||||
|
import:
|
||||||
|
- optional:nacos:test.yml
|
||||||
|
- optional:nacos:test01.yml?group=group_02
|
||||||
|
- optional:nacos:test02.yml?group=group_03&refreshEnabled=false
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.nacos.configdata;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigManager;
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||||
|
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
|
||||||
|
import com.alibaba.cloud.nacos.client.NacosPropertySource;
|
||||||
|
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
|
||||||
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.config.ConfigData;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLoader;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLoaderContext;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
|
||||||
|
import static com.alibaba.cloud.nacos.configdata.NacosConfigDataResource.NacosItemConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link ConfigDataLoader}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Load {@link ConfigData} via {@link NacosConfigDataResource}
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
public class NacosConfigDataLoader implements ConfigDataLoader<NacosConfigDataResource> {
|
||||||
|
|
||||||
|
private final Log log;
|
||||||
|
|
||||||
|
public NacosConfigDataLoader(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigData load(ConfigDataLoaderContext context,
|
||||||
|
NacosConfigDataResource resource) {
|
||||||
|
return doLoad(context, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigData doLoad(ConfigDataLoaderContext context,
|
||||||
|
NacosConfigDataResource resource) {
|
||||||
|
try {
|
||||||
|
ConfigService configService = getBean(context, NacosConfigManager.class)
|
||||||
|
.getConfigService();
|
||||||
|
NacosConfigProperties properties = getBean(context,
|
||||||
|
NacosConfigProperties.class);
|
||||||
|
|
||||||
|
NacosItemConfig config = resource.getConfig();
|
||||||
|
// pull config from nacos
|
||||||
|
List<PropertySource<?>> propertySources = pullConfig(configService,
|
||||||
|
config.getGroup(), config.getDataId(), config.getSuffix(),
|
||||||
|
properties.getTimeout());
|
||||||
|
|
||||||
|
NacosPropertySource propertySource = new NacosPropertySource(propertySources,
|
||||||
|
config.getGroup(), config.getDataId(), new Date(),
|
||||||
|
config.isRefreshEnabled());
|
||||||
|
|
||||||
|
NacosPropertySourceRepository.collectNacosPropertySource(propertySource);
|
||||||
|
|
||||||
|
// TODO Currently based on 2.4.2,
|
||||||
|
// compatibility needs to be done when upgrading to boot version 2.4.5
|
||||||
|
return new ConfigData(propertySources);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Error getting properties from nacos: " + resource, e);
|
||||||
|
}
|
||||||
|
if (!resource.isOptional()) {
|
||||||
|
throw new ConfigDataResourceNotFoundException(resource, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PropertySource<?>> pullConfig(ConfigService configService, String group,
|
||||||
|
String dataId, String suffix, long timeout)
|
||||||
|
throws NacosException, IOException {
|
||||||
|
String config = configService.getConfig(dataId, group, timeout);
|
||||||
|
return NacosDataParserHandler.getInstance().parseNacosData(dataId, config,
|
||||||
|
suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getBean(ConfigDataLoaderContext context, Class<T> type) {
|
||||||
|
if (context.getBootstrapContext().isRegistered(type)) {
|
||||||
|
return context.getBootstrapContext().get(type);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.nacos.configdata;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigManager;
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
|
||||||
|
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocation;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocationNotFoundException;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocationResolver;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataResource;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
|
||||||
|
import org.springframework.boot.context.config.Profiles;
|
||||||
|
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||||
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
|
||||||
|
import static com.alibaba.cloud.nacos.configdata.NacosConfigDataResource.NacosItemConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link ConfigDataLocationResolver}, load Nacos
|
||||||
|
* {@link ConfigDataResource}.
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
public class NacosConfigDataLocationResolver
|
||||||
|
implements ConfigDataLocationResolver<NacosConfigDataResource>, Ordered {
|
||||||
|
/**
|
||||||
|
* Prefix for Config Server imports.
|
||||||
|
*/
|
||||||
|
public static final String PREFIX = "nacos:";
|
||||||
|
|
||||||
|
private final Log log;
|
||||||
|
|
||||||
|
// support params
|
||||||
|
|
||||||
|
private static final String GROUP = "group";
|
||||||
|
|
||||||
|
private static final String REFRESH_ENABLED = "refreshEnabled";
|
||||||
|
|
||||||
|
public NacosConfigDataLocationResolver(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NacosConfigProperties loadProperties(
|
||||||
|
ConfigDataLocationResolverContext context) {
|
||||||
|
Binder binder = context.getBinder();
|
||||||
|
BindHandler bindHandler = getBindHandler(context);
|
||||||
|
|
||||||
|
NacosConfigProperties nacosConfigProperties;
|
||||||
|
if (context.getBootstrapContext().isRegistered(NacosConfigProperties.class)) {
|
||||||
|
nacosConfigProperties = context.getBootstrapContext()
|
||||||
|
.get(NacosConfigProperties.class);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nacosConfigProperties = binder
|
||||||
|
.bind("spring.cloud.nacos", Bindable.of(NacosConfigProperties.class),
|
||||||
|
bindHandler)
|
||||||
|
.map(properties -> binder
|
||||||
|
.bind(NacosConfigProperties.PREFIX,
|
||||||
|
Bindable.ofInstance(properties), bindHandler)
|
||||||
|
.orElse(properties))
|
||||||
|
.orElseGet(() -> binder
|
||||||
|
.bind(NacosConfigProperties.PREFIX,
|
||||||
|
Bindable.of(NacosConfigProperties.class), bindHandler)
|
||||||
|
.orElseGet(NacosConfigProperties::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nacosConfigProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BindHandler getBindHandler(ConfigDataLocationResolverContext context) {
|
||||||
|
return context.getBootstrapContext().getOrElse(BindHandler.class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Log getLog() {
|
||||||
|
return this.log;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResolvable(ConfigDataLocationResolverContext context,
|
||||||
|
ConfigDataLocation location) {
|
||||||
|
if (!location.hasPrefix(getPrefix())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return context.getBinder()
|
||||||
|
.bind(NacosConfigProperties.PREFIX + ".enabled", Boolean.class)
|
||||||
|
.orElse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getPrefix() {
|
||||||
|
return PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NacosConfigDataResource> resolve(
|
||||||
|
ConfigDataLocationResolverContext context, ConfigDataLocation location)
|
||||||
|
throws ConfigDataLocationNotFoundException,
|
||||||
|
ConfigDataResourceNotFoundException {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NacosConfigDataResource> resolveProfileSpecific(
|
||||||
|
ConfigDataLocationResolverContext resolverContext,
|
||||||
|
ConfigDataLocation location, Profiles profiles)
|
||||||
|
throws ConfigDataLocationNotFoundException {
|
||||||
|
NacosConfigProperties properties = loadProperties(resolverContext);
|
||||||
|
|
||||||
|
ConfigurableBootstrapContext bootstrapContext = resolverContext
|
||||||
|
.getBootstrapContext();
|
||||||
|
|
||||||
|
bootstrapContext.registerIfAbsent(NacosConfigProperties.class,
|
||||||
|
InstanceSupplier.of(properties));
|
||||||
|
|
||||||
|
registerConfigManager(properties, bootstrapContext);
|
||||||
|
|
||||||
|
return loadConfigDataResources(location, profiles, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<NacosConfigDataResource> loadConfigDataResources(
|
||||||
|
ConfigDataLocation location, Profiles profiles,
|
||||||
|
NacosConfigProperties properties) {
|
||||||
|
List<NacosConfigDataResource> result = new ArrayList<>();
|
||||||
|
URI uri = getUri(location, properties);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(dataIdFor(uri))) {
|
||||||
|
throw new IllegalArgumentException("dataId must be specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
NacosConfigDataResource resource = new NacosConfigDataResource(properties,
|
||||||
|
location.isOptional(), profiles, log,
|
||||||
|
new NacosItemConfig().setGroup(groupFor(uri, properties))
|
||||||
|
.setDataId(dataIdFor(uri)).setSuffix(suffixFor(uri, properties))
|
||||||
|
.setRefreshEnabled(refreshEnabledFor(uri, properties)));
|
||||||
|
result.add(resource);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private URI getUri(ConfigDataLocation location, NacosConfigProperties properties) {
|
||||||
|
String path = location.getNonPrefixedValue(getPrefix());
|
||||||
|
if (StringUtils.isBlank(path)) {
|
||||||
|
path = "/";
|
||||||
|
}
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
String uri = properties.getServerAddr() + path;
|
||||||
|
return getUri(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerConfigManager(NacosConfigProperties properties,
|
||||||
|
ConfigurableBootstrapContext bootstrapContext) {
|
||||||
|
if (!bootstrapContext.isRegistered(NacosConfigManager.class)) {
|
||||||
|
bootstrapContext.register(NacosConfigManager.class,
|
||||||
|
InstanceSupplier.of(new NacosConfigManager(properties)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private URI getUri(String uris) {
|
||||||
|
if (!uris.startsWith("http://") && !uris.startsWith("https://")) {
|
||||||
|
uris = "http://" + uris;
|
||||||
|
}
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(uris);
|
||||||
|
}
|
||||||
|
catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("illegal URI: " + uris);
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String groupFor(URI uri, NacosConfigProperties properties) {
|
||||||
|
Map<String, String> queryMap = getQueryMap(uri);
|
||||||
|
return queryMap.containsKey(GROUP) ? queryMap.get(GROUP) : properties.getGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getQueryMap(URI uri) {
|
||||||
|
String query = uri.getQuery();
|
||||||
|
if (StringUtils.isBlank(query)) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
Map<String, String> result = new HashMap<>(4);
|
||||||
|
for (String entry : query.split("&")) {
|
||||||
|
String[] kv = entry.split("=");
|
||||||
|
if (kv.length == 2) {
|
||||||
|
result.put(kv[0], kv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String suffixFor(URI uri, NacosConfigProperties properties) {
|
||||||
|
String dataId = dataIdFor(uri);
|
||||||
|
if (dataId != null && dataId.contains(".")) {
|
||||||
|
return dataId.substring(dataId.lastIndexOf('.') + 1);
|
||||||
|
}
|
||||||
|
return properties.getFileExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean refreshEnabledFor(URI uri, NacosConfigProperties properties) {
|
||||||
|
Map<String, String> queryMap = getQueryMap(uri);
|
||||||
|
return queryMap.containsKey(REFRESH_ENABLED)
|
||||||
|
? Boolean.parseBoolean(queryMap.get(REFRESH_ENABLED))
|
||||||
|
: properties.isRefreshEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dataIdFor(URI uri) {
|
||||||
|
String path = uri.getPath();
|
||||||
|
// notice '/'
|
||||||
|
if (path == null || path.length() <= 1) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
String[] parts = path.substring(1).split("/");
|
||||||
|
if (parts.length != 1) {
|
||||||
|
throw new IllegalArgumentException("illegal dataId");
|
||||||
|
}
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.nacos.configdata;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.config.ConfigDataResource;
|
||||||
|
import org.springframework.boot.context.config.Profiles;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
public class NacosConfigDataResource extends ConfigDataResource {
|
||||||
|
|
||||||
|
private final NacosConfigProperties properties;
|
||||||
|
|
||||||
|
private final boolean optional;
|
||||||
|
|
||||||
|
private final Profiles profiles;
|
||||||
|
|
||||||
|
private final Log log;
|
||||||
|
|
||||||
|
private final NacosItemConfig config;
|
||||||
|
|
||||||
|
public NacosConfigDataResource(NacosConfigProperties properties, boolean optional,
|
||||||
|
Profiles profiles, Log log, NacosItemConfig config) {
|
||||||
|
this.properties = properties;
|
||||||
|
this.optional = optional;
|
||||||
|
this.profiles = profiles;
|
||||||
|
this.log = log;
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosConfigProperties getProperties() {
|
||||||
|
return this.properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOptional() {
|
||||||
|
return this.optional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProfiles() {
|
||||||
|
return StringUtils.collectionToCommaDelimitedString(getAcceptedProfiles());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> getAcceptedProfiles() {
|
||||||
|
return this.profiles.getAccepted();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log getLog() {
|
||||||
|
return this.log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NacosConfigDataResource that = (NacosConfigDataResource) o;
|
||||||
|
return optional == that.optional && Objects.equals(properties, that.properties)
|
||||||
|
&& Objects.equals(profiles, that.profiles)
|
||||||
|
&& Objects.equals(log, that.log) && Objects.equals(config, that.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(properties, optional, profiles, log, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NacosConfigDataResource{" + "properties=" + properties + ", optional="
|
||||||
|
+ optional + ", profiles=" + profiles + ", config=" + config + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NacosItemConfig {
|
||||||
|
private String group;
|
||||||
|
private String dataId;
|
||||||
|
private String suffix;
|
||||||
|
private boolean refreshEnabled;
|
||||||
|
|
||||||
|
public NacosItemConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig(String group, String dataId, String suffix,
|
||||||
|
boolean refreshEnabled) {
|
||||||
|
this.group = group;
|
||||||
|
this.dataId = dataId;
|
||||||
|
this.suffix = suffix;
|
||||||
|
this.refreshEnabled = refreshEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig setDataId(String dataId) {
|
||||||
|
this.dataId = dataId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig setSuffix(String suffix) {
|
||||||
|
this.suffix = suffix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NacosItemConfig setRefreshEnabled(boolean refreshEnabled) {
|
||||||
|
this.refreshEnabled = refreshEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataId() {
|
||||||
|
return dataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuffix() {
|
||||||
|
return suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRefreshEnabled() {
|
||||||
|
return refreshEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NacosItemConfig that = (NacosItemConfig) o;
|
||||||
|
return refreshEnabled == that.refreshEnabled
|
||||||
|
&& Objects.equals(group, that.group)
|
||||||
|
&& Objects.equals(dataId, that.dataId)
|
||||||
|
&& Objects.equals(suffix, that.suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(group, dataId, suffix, refreshEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NacosItemConfig{" + "group='" + group + '\'' + ", dataId='" + dataId
|
||||||
|
+ '\'' + ", suffix='" + suffix + '\'' + ", refreshEnabled="
|
||||||
|
+ refreshEnabled + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2022 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.nacos;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NacosConfigAutoConfiguration Tester.
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
public class NacosConfigAutoConfigurationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noImports_thenCreateProperties() {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
NacosConfigAutoConfiguration.class);
|
||||||
|
|
||||||
|
assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
|
||||||
|
NacosConfigProperties.class).length).isEqualTo(1);
|
||||||
|
assertThat(context.getBean(NacosConfigProperties.class).getServerAddr())
|
||||||
|
.isEqualTo("localhost:8848");
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void imports_thenNoCreateProperties() {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
NacosConfigAutoConfiguration.class);
|
||||||
|
// mock import
|
||||||
|
context.registerBean(NacosConfigProperties.class, () -> {
|
||||||
|
NacosConfigProperties properties = new NacosConfigProperties();
|
||||||
|
properties.setServerAddr("localhost");
|
||||||
|
return properties;
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
|
||||||
|
NacosConfigProperties.class).length).isEqualTo(1);
|
||||||
|
assertThat(context.getBean(NacosConfigProperties.class).getServerAddr())
|
||||||
|
.isEqualTo("localhost");
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2022 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.alibaba.cloud.nacos.configdata;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||||
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocation;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
|
||||||
|
import org.springframework.boot.context.config.Profiles;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.boot.logging.DeferredLog;
|
||||||
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NacosConfigDataLocationResolver Tester.
|
||||||
|
*
|
||||||
|
* @author freeman
|
||||||
|
*/
|
||||||
|
public class NacosConfigDataLocationResolverTest {
|
||||||
|
|
||||||
|
private NacosConfigDataLocationResolver resolver;
|
||||||
|
|
||||||
|
private ConfigDataLocationResolverContext context = mock(
|
||||||
|
ConfigDataLocationResolverContext.class);
|
||||||
|
|
||||||
|
private MockEnvironment environment;
|
||||||
|
|
||||||
|
private Binder environmentBinder;
|
||||||
|
|
||||||
|
private ConfigurableBootstrapContext bootstrapContext = mock(
|
||||||
|
ConfigurableBootstrapContext.class);
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.environment = new MockEnvironment();
|
||||||
|
this.environmentBinder = Binder.get(this.environment);
|
||||||
|
this.resolver = new NacosConfigDataLocationResolver(new DeferredLog());
|
||||||
|
when(bootstrapContext.isRegistered(eq(ConfigService.class))).thenReturn(true);
|
||||||
|
when(context.getBinder()).thenReturn(environmentBinder);
|
||||||
|
when(context.getBootstrapContext()).thenReturn(bootstrapContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsResolvable_givenIncorrectPrefix_thenReturnFalse() {
|
||||||
|
assertThat(
|
||||||
|
this.resolver.isResolvable(this.context, ConfigDataLocation.of("test:")))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsResolvable_givenCorrectPrefix_thenReturnTure() {
|
||||||
|
assertThat(
|
||||||
|
this.resolver.isResolvable(this.context, ConfigDataLocation.of("nacos:")))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(this.resolver.isResolvable(this.context,
|
||||||
|
ConfigDataLocation.of("optional:nacos:"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsResolvable_givenDisable_thenReturnFalse() {
|
||||||
|
this.environment.setProperty(NacosConfigProperties.PREFIX + ".enabled", "false");
|
||||||
|
assertThat(
|
||||||
|
this.resolver.isResolvable(this.context, ConfigDataLocation.of("nacos:")))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testResolveProfileSpecific_givenNothing_thenReturnDefaultProfile() {
|
||||||
|
NacosConfigDataResource resource = testResolveProfileSpecific();
|
||||||
|
assertThat(resource.getProfiles()).isEqualTo("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testStartWithASlashIsOK() {
|
||||||
|
String locationUri = "nacos:/app";
|
||||||
|
List<NacosConfigDataResource> resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
assertThat(resources.get(0).getConfig().getDataId()).isEqualTo("app");
|
||||||
|
|
||||||
|
locationUri = "nacos:app";
|
||||||
|
resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
assertThat(resources.get(0).getConfig().getDataId()).isEqualTo("app");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDataIdMustBeSpecified() {
|
||||||
|
String locationUri = "nacos:";
|
||||||
|
assertThatThrownBy(() -> testUri(locationUri))
|
||||||
|
.hasMessage("dataId must be specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInvalidDataId() {
|
||||||
|
String locationUri = "nacos:test/test.yml";
|
||||||
|
assertThatThrownBy(() -> testUri(locationUri)).hasMessage("illegal dataId");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenCustomizeSuffix_thenOverrideDefault() {
|
||||||
|
String locationUri = "nacos:app";
|
||||||
|
List<NacosConfigDataResource> resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
assertThat(resources.get(0).getConfig().getDataId()).isEqualTo("app");
|
||||||
|
assertThat(resources.get(0).getConfig().getSuffix()).isEqualTo("properties");
|
||||||
|
|
||||||
|
environment.setProperty("spring.cloud.nacos.config.file-extension", "yml");
|
||||||
|
locationUri = "nacos:app";
|
||||||
|
resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
assertThat(resources.get(0).getConfig().getDataId()).isEqualTo("app");
|
||||||
|
assertThat(resources.get(0).getConfig().getSuffix()).isEqualTo("yml");
|
||||||
|
|
||||||
|
locationUri = "nacos:app.json";
|
||||||
|
resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
assertThat(resources.get(0).getConfig().getDataId()).isEqualTo("app.json");
|
||||||
|
assertThat(resources.get(0).getConfig().getSuffix()).isEqualTo("json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUrisInLocationShouldOverridesProperty() {
|
||||||
|
environment.setProperty("spring.cloud.nacos.config.group", "default");
|
||||||
|
environment.setProperty("spring.cloud.nacos.config.refreshEnabled", "true");
|
||||||
|
String locationUri = "nacos:test.yml?group=not_default&refreshEnabled=false";
|
||||||
|
List<NacosConfigDataResource> resources = testUri(locationUri);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
NacosConfigDataResource resource = resources.get(0);
|
||||||
|
assertThat(resource.getConfig().getGroup()).isEqualTo("not_default");
|
||||||
|
assertThat(resource.getConfig().getSuffix()).isEqualTo("yml");
|
||||||
|
assertThat(resource.getConfig().isRefreshEnabled()).isFalse();
|
||||||
|
assertThat(resource.getConfig().getDataId()).isEqualTo("test.yml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetCommonPropertiesIsOK() {
|
||||||
|
environment.setProperty("spring.cloud.nacos.username", "root");
|
||||||
|
environment.setProperty("spring.cloud.nacos.password", "root");
|
||||||
|
environment.setProperty("spring.cloud.nacos.server-addr", "localhost:8888");
|
||||||
|
String locationUri = "nacos:test.yml";
|
||||||
|
List<NacosConfigDataResource> resources = testUri(locationUri);
|
||||||
|
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
NacosConfigDataResource resource = resources.get(0);
|
||||||
|
assertThat(resource.getProperties().getUsername()).isEqualTo("root");
|
||||||
|
assertThat(resource.getProperties().getPassword()).isEqualTo("root");
|
||||||
|
assertThat(resource.getProperties().getServerAddr()).isEqualTo("localhost:8888");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCommonPropertiesHasLowerPriority() {
|
||||||
|
environment.setProperty("spring.cloud.nacos.username", "root");
|
||||||
|
environment.setProperty("spring.cloud.nacos.password", "root");
|
||||||
|
environment.setProperty("spring.cloud.nacos.config.password", "not_root");
|
||||||
|
environment.setProperty("spring.cloud.nacos.server-addr", "localhost:8888");
|
||||||
|
environment.setProperty("spring.cloud.nacos.config.server-addr",
|
||||||
|
"localhost:9999");
|
||||||
|
String locationUri = "nacos:test.yml";
|
||||||
|
List<NacosConfigDataResource> resources = testUri(locationUri);
|
||||||
|
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
NacosConfigDataResource resource = resources.get(0);
|
||||||
|
assertThat(resource.getProperties().getUsername()).isEqualTo("root");
|
||||||
|
assertThat(resource.getProperties().getPassword()).isEqualTo("not_root");
|
||||||
|
assertThat(resource.getProperties().getServerAddr()).isEqualTo("localhost:9999");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<NacosConfigDataResource> testUri(String locationUri,
|
||||||
|
String... activeProfiles) {
|
||||||
|
Profiles profiles = mock(Profiles.class);
|
||||||
|
when(profiles.getActive()).thenReturn(Arrays.asList(activeProfiles));
|
||||||
|
return this.resolver.resolveProfileSpecific(context,
|
||||||
|
ConfigDataLocation.of(locationUri), profiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenNoneInBootstrapContext_thenCreateNewConfigClientProperties() {
|
||||||
|
when(bootstrapContext.isRegistered(eq(NacosConfigProperties.class)))
|
||||||
|
.thenReturn(false);
|
||||||
|
when(bootstrapContext.get(eq(NacosConfigProperties.class)))
|
||||||
|
.thenReturn(new NacosConfigProperties());
|
||||||
|
List<NacosConfigDataResource> resources = this.resolver.resolveProfileSpecific(
|
||||||
|
context, ConfigDataLocation.of("nacos:test.yml"), mock(Profiles.class));
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
verify(bootstrapContext, times(0)).get(eq(NacosConfigProperties.class));
|
||||||
|
NacosConfigDataResource resource = resources.get(0);
|
||||||
|
assertThat(resource.getConfig().getGroup()).isEqualTo("DEFAULT_GROUP");
|
||||||
|
assertThat(resource.getConfig().getDataId()).isEqualTo("test.yml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private NacosConfigDataResource testResolveProfileSpecific() {
|
||||||
|
return testResolveProfileSpecific("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
private NacosConfigDataResource testResolveProfileSpecific(String activeProfile) {
|
||||||
|
Profiles profiles = mock(Profiles.class);
|
||||||
|
if (activeProfile != null) {
|
||||||
|
when(profiles.getActive())
|
||||||
|
.thenReturn(Collections.singletonList(activeProfile));
|
||||||
|
when(profiles.getAccepted())
|
||||||
|
.thenReturn(Collections.singletonList(activeProfile));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NacosConfigDataResource> resources = this.resolver.resolveProfileSpecific(
|
||||||
|
context, ConfigDataLocation.of("nacos:test.yml"), profiles);
|
||||||
|
assertThat(resources).hasSize(1);
|
||||||
|
return resources.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue