mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
add module nacos-config and nacos-discovery
This commit is contained in:
76
spring-cloud-alibaba-nacos-config/pom.xml
Normal file
76
spring-cloud-alibaba-nacos-config/pom.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba</artifactId>
|
||||
<version>0.2.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
|
||||
<name>Spring Cloud Alibaba Nacos Config</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--spring cloud-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--spring boot-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshProperties;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author juven.xuxb
|
||||
*/
|
||||
@Configuration
|
||||
public class NacosConfigAutoConfiguration implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private NacosConfigProperties nacosConfigProperties;
|
||||
|
||||
@Autowired
|
||||
private NacosRefreshProperties nacosRefreshProperties;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Bean
|
||||
public NacosConfigProperties nacosConfigProperties() {
|
||||
return new NacosConfigProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosPropertySourceRepository nacosPropertySourceRepository() {
|
||||
return new NacosPropertySourceRepository(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosRefreshProperties nacosRefreshProperties() {
|
||||
return new NacosRefreshProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosRefreshHistory nacosRefreshHistory() {
|
||||
return new NacosRefreshHistory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosContextRefresher nacosContextRefresher(ContextRefresher contextRefresher,
|
||||
NacosRefreshHistory refreshHistory,
|
||||
NacosPropertySourceRepository propertySourceRepository,
|
||||
ConfigService configService) {
|
||||
return new NacosContextRefresher(contextRefresher, nacosConfigProperties,
|
||||
nacosRefreshProperties, refreshHistory, propertySourceRepository,configService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
@Configuration
|
||||
public class NacosConfigBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
public NacosPropertySourceLocator nacosPropertySourceLocator() {
|
||||
return new NacosPropertySourceLocator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosConfigProperties nacosConfigProperties() {
|
||||
return new NacosConfigProperties();
|
||||
}
|
||||
}
|
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* nacos properties
|
||||
*
|
||||
* @author leijuan
|
||||
* @author xiaojing
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.nacos.config")
|
||||
public class NacosConfigProperties {
|
||||
|
||||
/**
|
||||
* nacos config server address
|
||||
*/
|
||||
private String serverAddr;
|
||||
|
||||
/**
|
||||
* nacos config encode
|
||||
*/
|
||||
private String encode;
|
||||
|
||||
/**
|
||||
* nacos config group
|
||||
*/
|
||||
private String group = "DEFAULT_GROUP";
|
||||
|
||||
/**
|
||||
* nacos config dataId prefix
|
||||
*/
|
||||
private String prefix;
|
||||
/**
|
||||
* nacos config dataId contentType
|
||||
*/
|
||||
private String contentType = "properties";
|
||||
|
||||
/**
|
||||
* timeout to get configuration
|
||||
*/
|
||||
private int timeout;
|
||||
|
||||
/**
|
||||
* endpoint for Nacos
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* Nacos namespace
|
||||
*/
|
||||
private String namespace;
|
||||
|
||||
/**
|
||||
* Nacos access key
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* Nacos secret key
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* nacos config context path
|
||||
*/
|
||||
private String contextPath;
|
||||
|
||||
/**
|
||||
* nacos config cluster name
|
||||
*/
|
||||
private String clusterName;
|
||||
|
||||
//todo sts support
|
||||
|
||||
public String getServerAddr() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
public void setServerAddr(String serverAddr) {
|
||||
this.serverAddr = serverAddr;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getEncode() {
|
||||
return encode;
|
||||
}
|
||||
|
||||
public void setEncode(String encode) {
|
||||
this.encode = encode;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
return contextPath;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public void setClusterName(String clusterName) {
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NacosConfigProperties{" +
|
||||
"serverAddr='" + serverAddr + '\'' +
|
||||
", encode='" + encode + '\'' +
|
||||
", group='" + group + '\'' +
|
||||
", prefix='" + prefix + '\'' +
|
||||
", contentType='" + contentType + '\'' +
|
||||
", timeout=" + timeout +
|
||||
", endpoint='" + endpoint + '\'' +
|
||||
", namespace='" + namespace + '\'' +
|
||||
", accessKey='" + accessKey + '\'' +
|
||||
", secretKey='" + secretKey + '\'' +
|
||||
", contextPath='" + contextPath + '\'' +
|
||||
", clusterName='" + clusterName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
public void overrideFromEnv(Environment env){
|
||||
|
||||
if(StringUtils.isEmpty(this.getServerAddr())) {
|
||||
this.setServerAddr(env.resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getEncode())) {
|
||||
this.setEncode(env.resolvePlaceholders("${spring.cloud.nacos.config.encode:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getNamespace())) {
|
||||
this.setNamespace(env.resolvePlaceholders("${spring.cloud.nacos.config.namespace:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getAccessKey())) {
|
||||
this.setAccessKey(env.resolvePlaceholders("${spring.cloud.nacos.config.access-key:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getSecretKey())) {
|
||||
this.setSecretKey(env.resolvePlaceholders("${spring.cloud.nacos.config.secret-key:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getContextPath())) {
|
||||
this.setContextPath(env.resolvePlaceholders("${spring.cloud.nacos.config.context-path:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getClusterName())) {
|
||||
this.setClusterName(env.resolvePlaceholders("${spring.cloud.nacos.config.cluster-name:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getEndpoint())) {
|
||||
this.setEndpoint(env.resolvePlaceholders("${spring.cloud.nacos.config.endpoint:}"));
|
||||
}
|
||||
if(StringUtils.isEmpty(this.getPrefix())) {
|
||||
this.setPrefix(env.resolvePlaceholders("${spring.cloud.nacos.config.prefix:}"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosPropertySourceRepository {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public NacosPropertySourceRepository(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all nacos properties from application context
|
||||
*/
|
||||
public List<NacosPropertySource> getAll() {
|
||||
List<NacosPropertySource> result = new ArrayList<>();
|
||||
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;
|
||||
for (PropertySource p : ctx.getEnvironment().getPropertySources()) {
|
||||
if (p instanceof NacosPropertySource) {
|
||||
result.add((NacosPropertySource) p);
|
||||
}
|
||||
else if (p instanceof CompositePropertySource) {
|
||||
collectNacosPropertySources((CompositePropertySource) p, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void collectNacosPropertySources(CompositePropertySource composite,
|
||||
List<NacosPropertySource> result) {
|
||||
for (PropertySource p : composite.getPropertySources()) {
|
||||
if (p instanceof NacosPropertySource) {
|
||||
result.add((NacosPropertySource) p);
|
||||
}
|
||||
else if (p instanceof CompositePropertySource) {
|
||||
collectNacosPropertySources((CompositePropertySource) p, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.client;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosPropertySource extends MapPropertySource {
|
||||
|
||||
/**
|
||||
* Nacos dataID
|
||||
*/
|
||||
private final String dataId;
|
||||
|
||||
/**
|
||||
* timestamp the property get
|
||||
*/
|
||||
private final Date timestamp;
|
||||
|
||||
|
||||
NacosPropertySource(String dataId, Map<String, Object> source, Date timestamp) {
|
||||
super(dataId, source);
|
||||
this.dataId = dataId;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.client;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosPropertySourceBuilder {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(NacosPropertySourceBuilder.class);
|
||||
|
||||
private ConfigService configService;
|
||||
private long timeout;
|
||||
|
||||
public NacosPropertySourceBuilder() {
|
||||
}
|
||||
|
||||
public NacosPropertySourceBuilder(ConfigService configService, long timeout) {
|
||||
this.configService = configService;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public long getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(long timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public ConfigService getConfigService() {
|
||||
return configService;
|
||||
}
|
||||
|
||||
public void setConfigService(ConfigService configService) {
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataId Nacos dataId
|
||||
* @param group Nacos group
|
||||
*/
|
||||
NacosPropertySource build(String dataId, String group, String contentType) {
|
||||
Properties p = loadNacosData(dataId, group, contentType);
|
||||
if (p == null) {
|
||||
return null;
|
||||
}
|
||||
return new NacosPropertySource(dataId, propertiesToMap(p), new Date());
|
||||
}
|
||||
|
||||
private Properties loadNacosData(String dataId, String group, String contentType) {
|
||||
String data = null;
|
||||
try {
|
||||
data = configService.getConfig(dataId, group, timeout);
|
||||
// todo add content type yaml support
|
||||
if (!StringUtils.isEmpty(data)) {
|
||||
Properties properties = new Properties();
|
||||
logger.info(String.format("Loading nacos data, dataId: '%s', group: '%s'",
|
||||
dataId, group));
|
||||
properties.load(new StringReader(data));
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
catch (NacosException e) {
|
||||
logger.error("get data from Nacos error,dataId:{}, ", dataId, e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("parse data from Nacos error,dataId:{},data:{},", dataId, data,
|
||||
e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> propertiesToMap(Properties properties) {
|
||||
Map<String, Object> result = new HashMap<>(16);
|
||||
Enumeration<String> keys = (Enumeration<String>) properties.propertyNames();
|
||||
while (keys.hasMoreElements()) {
|
||||
String key = keys.nextElement();
|
||||
Object value = properties.getProperty(key);
|
||||
if (value != null) {
|
||||
result.put(key, ((String) value).trim());
|
||||
}
|
||||
else {
|
||||
result.put(key, null);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.client;
|
||||
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.alibaba.nacos.api.NacosFactory;
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import static com.alibaba.nacos.api.PropertyKeyConst.*;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
@Order(0)
|
||||
public class NacosPropertySourceLocator implements PropertySourceLocator {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(NacosPropertySourceLocator.class);
|
||||
private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
|
||||
private static final String SEP1 = "-";
|
||||
private static final String DOT = ".";
|
||||
|
||||
@Autowired
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
private NacosConfigProperties nacosConfigProperties;
|
||||
|
||||
private ConfigService configService;
|
||||
|
||||
private NacosPropertySourceBuilder nacosPropertySourceBuilder;
|
||||
|
||||
private Properties getPropertiesFromEnv(Environment env) {
|
||||
|
||||
nacosConfigProperties.overrideFromEnv(env);
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.put(SERVER_ADDR, nacosConfigProperties.getServerAddr());
|
||||
properties.put(ENCODE, nacosConfigProperties.getEncode());
|
||||
properties.put(NAMESPACE, nacosConfigProperties.getNamespace());
|
||||
properties.put(ACCESS_KEY, nacosConfigProperties.getAccessKey());
|
||||
properties.put(SECRET_KEY, nacosConfigProperties.getSecretKey());
|
||||
properties.put(CONTEXT_PATH, nacosConfigProperties.getContextPath());
|
||||
properties.put(CLUSTER_NAME, nacosConfigProperties.getClusterName());
|
||||
properties.put(ENDPOINT, nacosConfigProperties.getEndpoint());
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertySource<?> locate(Environment env) {
|
||||
|
||||
Properties properties = getPropertiesFromEnv(env);
|
||||
|
||||
try {
|
||||
configService = NacosFactory.createConfigService(properties);
|
||||
}
|
||||
catch (NacosException e) {
|
||||
// todo 为什么这里是 checkException,什么时候会抛出,什么时候需要关心
|
||||
logger.error("create config service error, nacosConfigProperties:{}, ", properties, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
beanFactory.registerSingleton("configService", configService);
|
||||
|
||||
if (null == configService) {
|
||||
logger.warn(
|
||||
"no instance of config service found, can't load config from nacos");
|
||||
return null;
|
||||
}
|
||||
long timeout = nacosConfigProperties.getTimeout();
|
||||
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout);
|
||||
|
||||
String applicationName = env.getProperty("spring.application.name");
|
||||
logger.info("Initialize spring.application.name '" + applicationName + "'.");
|
||||
|
||||
String nacosGroup = nacosConfigProperties.getGroup();
|
||||
String dataIdPrefix = nacosConfigProperties.getPrefix();
|
||||
if (StringUtils.isEmpty(dataIdPrefix)) {
|
||||
dataIdPrefix = applicationName;
|
||||
}
|
||||
|
||||
String contentType = nacosConfigProperties.getContentType();
|
||||
|
||||
CompositePropertySource composite = new CompositePropertySource(
|
||||
NACOS_PROPERTY_SOURCE_NAME);
|
||||
|
||||
loadApplicationConfiguration(composite, env, nacosGroup, dataIdPrefix, contentType);
|
||||
|
||||
return composite;
|
||||
}
|
||||
|
||||
private void loadApplicationConfiguration(
|
||||
CompositePropertySource compositePropertySource, Environment environment,
|
||||
String nacosGroup, String dataIdPrefix, String contentType) {
|
||||
loadNacosDataIfPresent(compositePropertySource, dataIdPrefix + DOT + contentType,
|
||||
nacosGroup, contentType);
|
||||
for (String profile : environment.getActiveProfiles()) {
|
||||
String dataId = dataIdPrefix + SEP1 + profile + DOT + contentType;
|
||||
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
|
||||
contentType);
|
||||
}
|
||||
// todo multi profile active order and priority
|
||||
}
|
||||
|
||||
private void loadNacosDataIfPresent(final CompositePropertySource composite,
|
||||
final String dataId, final String group,String contentType) {
|
||||
NacosPropertySource ps = nacosPropertySourceBuilder.build(dataId, group, contentType);
|
||||
if (ps != null) {
|
||||
composite.addFirstPropertySource(ps);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.diagnostics.analyzer;
|
||||
|
||||
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
|
||||
/**
|
||||
* A {@code FailureAnalyzer} that performs analysis of failures caused by a
|
||||
* {@code NacosConnectionFailureException}.
|
||||
*
|
||||
* @author juven.xuxb
|
||||
*/
|
||||
public class NacosConnectionFailureAnalyzer
|
||||
extends AbstractFailureAnalyzer<NacosConnectionFailureException> {
|
||||
|
||||
@Override
|
||||
protected FailureAnalysis analyze(Throwable rootFailure,
|
||||
NacosConnectionFailureException cause) {
|
||||
return new FailureAnalysis("Application failed to connect to Nacos server",
|
||||
"check your nacos server config", cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.diagnostics.analyzer;
|
||||
|
||||
/**
|
||||
* A {@code NacosConnectionFailureException} is thrown when the application fails to connect
|
||||
* to Nacos Server.
|
||||
*
|
||||
* @author juven.xuxb
|
||||
*/
|
||||
public class NacosConnectionFailureException extends RuntimeException {
|
||||
|
||||
private final String domain;
|
||||
|
||||
private final String port;
|
||||
|
||||
public NacosConnectionFailureException(String domain, String port, String message) {
|
||||
super(message);
|
||||
this.domain = domain;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public NacosConnectionFailureException(String domain, String port, String message,
|
||||
Throwable cause) {
|
||||
super(message, cause);
|
||||
this.domain = domain;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
String getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.endpoint;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
|
||||
|
||||
/**
|
||||
* Endpoint for Nacos, contains config data and refresh history
|
||||
* @author xiaojing
|
||||
*/
|
||||
@Endpoint(id = "nacos-config")
|
||||
public class NacosConfigEndpoint {
|
||||
|
||||
private final NacosConfigProperties properties;
|
||||
|
||||
private final NacosRefreshHistory refreshHistory;
|
||||
|
||||
private final NacosPropertySourceRepository propertySourceRepository;
|
||||
|
||||
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public NacosConfigEndpoint(NacosConfigProperties properties, NacosRefreshHistory refreshHistory,
|
||||
NacosPropertySourceRepository propertySourceRepository) {
|
||||
this.properties = properties;
|
||||
this.refreshHistory = refreshHistory;
|
||||
this.propertySourceRepository = propertySourceRepository;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new HashMap<>(16);
|
||||
result.put("NacosConfigProperties", properties);
|
||||
|
||||
List<NacosPropertySource> all = propertySourceRepository.getAll();
|
||||
|
||||
List<Map<String, Object>> sources = new ArrayList<>();
|
||||
for (NacosPropertySource ps : all) {
|
||||
Map<String, Object> source = new HashMap<>(16);
|
||||
source.put("dataId", ps.getDataId());
|
||||
source.put("lastSynced", dateFormat.format(ps.getTimestamp()));
|
||||
sources.add(source);
|
||||
}
|
||||
result.put("Sources", sources);
|
||||
result.put("RefreshHistory", refreshHistory.getRecords());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.endpoint;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnClass(value = Endpoint.class)
|
||||
public class NacosConfigEndpointAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private NacosConfigProperties nacosConfigProperties;
|
||||
|
||||
@Autowired
|
||||
private NacosRefreshHistory nacosRefreshHistory;
|
||||
|
||||
@Autowired
|
||||
private NacosPropertySourceRepository nacosPropertySourceRepository;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
public NacosConfigProperties nacosConfigProperties() {
|
||||
return new NacosConfigProperties();
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
@Bean
|
||||
public NacosConfigEndpoint nacosConfigEndpoint() {
|
||||
return new NacosConfigEndpoint(nacosConfigProperties, nacosRefreshHistory,
|
||||
nacosPropertySourceRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosConfigHealthIndicator nacosConfigHealthIndicator(
|
||||
NacosPropertySourceRepository nacosPropertySourceRepository) {
|
||||
return new NacosConfigHealthIndicator(nacosConfigProperties,
|
||||
nacosPropertySourceRepository, configService);
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.endpoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosConfigHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
private final NacosConfigProperties nacosConfigProperties;
|
||||
|
||||
private final NacosPropertySourceRepository nacosPropertySourceRepository;
|
||||
|
||||
private final List<String> dataIds;
|
||||
|
||||
private final ConfigService configService;
|
||||
|
||||
public NacosConfigHealthIndicator(NacosConfigProperties nacosConfigProperties,
|
||||
NacosPropertySourceRepository nacosPropertySourceRepository,
|
||||
ConfigService configService) {
|
||||
this.nacosConfigProperties = nacosConfigProperties;
|
||||
this.nacosPropertySourceRepository = nacosPropertySourceRepository;
|
||||
this.configService = configService;
|
||||
|
||||
this.dataIds = new ArrayList<>();
|
||||
for (NacosPropertySource nacosPropertySource : this.nacosPropertySourceRepository
|
||||
.getAll()) {
|
||||
this.dataIds.add(nacosPropertySource.getDataId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
for (String dataId : dataIds) {
|
||||
try {
|
||||
String config = configService.getConfig(dataId,
|
||||
nacosConfigProperties.getGroup(),
|
||||
nacosConfigProperties.getTimeout());
|
||||
if (StringUtils.isEmpty(config)) {
|
||||
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
|
||||
dataId, nacosConfigProperties.getGroup()), "config is empty");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
|
||||
dataId, nacosConfigProperties.getGroup()), e.getMessage());
|
||||
}
|
||||
}
|
||||
builder.up().withDetail("dataIds", dataIds);
|
||||
}
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.refresh;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.config.listener.Listener;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
/**
|
||||
* On application start up, NacosContextRefresher add nacos listeners to all application
|
||||
* level dataIds, when there is a change in the data, listeners will refresh
|
||||
* configurations.
|
||||
*
|
||||
* @author juven.xuxb
|
||||
*/
|
||||
public class NacosContextRefresher implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(NacosContextRefresher.class);
|
||||
|
||||
private final ContextRefresher contextRefresher;
|
||||
|
||||
private final NacosConfigProperties properties;
|
||||
|
||||
private final NacosRefreshProperties refreshProperties;
|
||||
|
||||
private final NacosRefreshHistory refreshHistory;
|
||||
|
||||
private final NacosPropertySourceRepository nacosPropertySourceRepository;
|
||||
|
||||
private final ConfigService configService;
|
||||
|
||||
private Map<String,Listener> listenerMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
public NacosContextRefresher(ContextRefresher contextRefresher,
|
||||
NacosConfigProperties properties, NacosRefreshProperties refreshProperties,
|
||||
NacosRefreshHistory refreshHistory,
|
||||
NacosPropertySourceRepository nacosPropertySourceRepository,
|
||||
ConfigService configService) {
|
||||
this.contextRefresher = contextRefresher;
|
||||
this.properties = properties;
|
||||
this.refreshProperties = refreshProperties;
|
||||
this.refreshHistory = refreshHistory;
|
||||
this.nacosPropertySourceRepository = nacosPropertySourceRepository;
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
this.registerNacosListenersForApplications();
|
||||
}
|
||||
|
||||
private void registerNacosListenersForApplications() {
|
||||
if (refreshProperties.isEnabled()) {
|
||||
for (NacosPropertySource nacosPropertySource : nacosPropertySourceRepository
|
||||
.getAll()) {
|
||||
String dataId = nacosPropertySource.getDataId();
|
||||
registerNacosListener(dataId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerNacosListener(final String dataId) {
|
||||
|
||||
Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
String md5 = "";
|
||||
if (!StringUtils.isEmpty(configInfo)) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md5 = new BigInteger(1, md.digest(configInfo.getBytes("UTF-8")))
|
||||
.toString(16);
|
||||
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
|
||||
logger.warn("unable to get md5 for dataId: " + dataId, e);
|
||||
}
|
||||
}
|
||||
refreshHistory.add(dataId, md5);
|
||||
contextRefresher.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor getExecutor() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
configService.addListener(dataId, properties.getGroup(), listener);
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.refresh;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class NacosRefreshHistory {
|
||||
|
||||
private static final int MAX_SIZE = 20;
|
||||
|
||||
private LinkedList<Record> records = new LinkedList<>();
|
||||
|
||||
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public void add(String dataId, String md5) {
|
||||
records.addFirst(new Record(dateFormat.format(new Date()), dataId, md5));
|
||||
if (records.size() > MAX_SIZE) {
|
||||
records.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
public LinkedList<Record> getRecords() {
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
||||
class Record {
|
||||
|
||||
private final String timestamp;
|
||||
|
||||
private final String dataId;
|
||||
|
||||
private final String md5;
|
||||
|
||||
public Record(String timestamp, String dataId, String md5) {
|
||||
this.timestamp = timestamp;
|
||||
this.dataId = dataId;
|
||||
this.md5 = md5;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos.refresh;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
@Component
|
||||
public class NacosRefreshProperties {
|
||||
|
||||
@Value("${spring.cloud.nacos.config.refresh.enabled:true}")
|
||||
private boolean enabled = true;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.cloud.nacos.config.server-addr",
|
||||
"type": "java.lang.String",
|
||||
"defaultValue": "",
|
||||
"description": "nacos config server address."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.nacos.config.timeout",
|
||||
"type": "java.lang.Long",
|
||||
"defaultValue": 3000,
|
||||
"description": "sentinel api port."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.sentinel.dashboard",
|
||||
"type": "java.lang.String",
|
||||
"description": "sentinel dashboard address, won't try to connect dashboard when address is empty."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.sentinel.filter.order",
|
||||
"type": "java.lang.Integer",
|
||||
"defaultValue": "Integer.MIN_VALUE",
|
||||
"description": "Sentinel filter chain order, will be set to FilterRegistrationBean."
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.sentinel.filter.urlPatterns",
|
||||
"type": "java.util.List",
|
||||
"description": "URL pattern for Sentinel filter, default contains '/*'."
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.alibaba.nacos.NacosConfigBootstrapConfiguration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.alibaba.nacos.NacosConfigAutoConfiguration,\
|
||||
org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpointAutoConfiguration
|
||||
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||
org.springframework.cloud.alibaba.nacos..analyzer.NacosConnectionFailureAnalyzerdiagnostics
|
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
|
||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshProperties;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.cloud.context.scope.refresh.RefreshScope;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosConfigAutoConfigurationTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.context = new SpringApplicationBuilder(
|
||||
NacosConfigBootstrapConfiguration.class,
|
||||
NacosConfigAutoConfiguration.class,
|
||||
TestConfiguration.class)
|
||||
.web(WebApplicationType.NONE).run(
|
||||
"--spring.cloud.config.enabled=true",
|
||||
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
||||
"--spring.cloud.nacos.config.prefix=myapp");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNacosConfigProperties() {
|
||||
|
||||
NacosPropertySourceLocator nacosPropertySourceLocator = this.context.getBean(NacosPropertySourceLocator.class);
|
||||
Environment environment = this.context.getEnvironment();
|
||||
try{
|
||||
nacosPropertySourceLocator.locate(environment);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
|
||||
NacosConfigProperties nacosConfigProperties = this.context.getBean(NacosConfigProperties.class);
|
||||
assertThat(nacosConfigProperties.getContentType()).isEqualTo("properties");
|
||||
assertThat(nacosConfigProperties.getPrefix()).isEqualTo("myapp");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNacosRefreshProperties() {
|
||||
|
||||
NacosRefreshProperties nacosRefreshProperties = this.context.getBean(NacosRefreshProperties.class);
|
||||
assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true);
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureBefore(NacosConfigAutoConfiguration.class)
|
||||
static class TestConfiguration{
|
||||
|
||||
|
||||
@Autowired
|
||||
ConfigurableApplicationContext context;
|
||||
|
||||
@Bean
|
||||
ContextRefresher contextRefresher(){
|
||||
return new ContextRefresher(context, new RefreshScope());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.alibaba.nacos;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author xiaojing
|
||||
*/
|
||||
public class NacosConfigBootstrapConfigurationTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.context = new SpringApplicationBuilder(
|
||||
NacosConfigBootstrapConfiguration.class).web(WebApplicationType.NONE).run(
|
||||
"--spring.cloud.config.enabled=true",
|
||||
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
||||
"--spring.cloud.nacos.config.prefix=myapp");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNacosPropertySourceLocator() {
|
||||
|
||||
NacosPropertySourceLocator locator = this.context
|
||||
.getBean(NacosPropertySourceLocator.class);
|
||||
Environment environment = this.context.getEnvironment();
|
||||
try {
|
||||
locator.locate(environment);
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
Field configServiceField = ReflectionUtils
|
||||
.findField(NacosPropertySourceLocator.class, "configService");
|
||||
configServiceField.setAccessible(true);
|
||||
|
||||
ConfigService configService = (ConfigService) ReflectionUtils
|
||||
.getField(configServiceField, locator);
|
||||
|
||||
assertThat(configService).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user