feat:自定义 @ConfigurationProperties注解的类属性值更新处理方式
This commit is contained in:
parent
b1d810de95
commit
49860000fc
|
@ -29,6 +29,9 @@
|
||||||
- 20241206 读取本地配置缓存(连接服务端失败后的兜底操作)
|
- 20241206 读取本地配置缓存(连接服务端失败后的兜底操作)
|
||||||
- 20241207 动态更新@Value注解的属性
|
- 20241207 动态更新@Value注解的属性
|
||||||
- 20241207 动态更新@ConfigurationProperties注解类中的属性
|
- 20241207 动态更新@ConfigurationProperties注解类中的属性
|
||||||
|
- 感想:太艰难了
|
||||||
|
- 感谢:spring-cloud-context 给我的灵感
|
||||||
|
- 耗时:4小时
|
||||||
- 202412xx 动态替换配置指令实现 [loading]
|
- 202412xx 动态替换配置指令实现 [loading]
|
||||||
|
|
||||||
#### 服务端
|
#### 服务端
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
<artifactId>kenaito-config-common</artifactId>
|
<artifactId>kenaito-config-common</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||||
<artifactId>spring-cloud-context</artifactId>
|
<!-- <artifactId>spring-cloud-context</artifactId>-->
|
||||||
<version>4.2.0</version>
|
<!-- <version>4.2.0</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -5,15 +5,6 @@ import cn.hutool.core.thread.ThreadUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.odboy.config.model.msgtype.ClientInfo;
|
import cn.odboy.config.model.msgtype.ClientInfo;
|
||||||
import cn.odboy.config.netty.ConfigClient;
|
import cn.odboy.config.netty.ConfigClient;
|
||||||
import java.io.File;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
|
@ -25,6 +16,16 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置加载器
|
* 配置加载器
|
||||||
*
|
*
|
||||||
|
@ -35,7 +36,9 @@ import org.yaml.snakeyaml.Yaml;
|
||||||
public class ClientConfigLoader {
|
public class ClientConfigLoader {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ClientConfigLoader.class);
|
private static final Logger logger = LoggerFactory.getLogger(ClientConfigLoader.class);
|
||||||
|
|
||||||
/** 默认的配置值 */
|
/**
|
||||||
|
* 默认的配置值
|
||||||
|
*/
|
||||||
private static final String OS_TYPE_WIN = "win";
|
private static final String OS_TYPE_WIN = "win";
|
||||||
|
|
||||||
private static final String OS_TYPE_MAC = "mac";
|
private static final String OS_TYPE_MAC = "mac";
|
||||||
|
@ -47,49 +50,79 @@ public class ClientConfigLoader {
|
||||||
private static final String DEFAULT_CONFIG_DATA_ID = "default";
|
private static final String DEFAULT_CONFIG_DATA_ID = "default";
|
||||||
private static final String DEFAULT_PATH_WIN_SEP = ":";
|
private static final String DEFAULT_PATH_WIN_SEP = ":";
|
||||||
|
|
||||||
/** 默认配置项:配置中心服务ip */
|
/**
|
||||||
|
* 默认配置项:配置中心服务ip
|
||||||
|
*/
|
||||||
private static final String DEFAULT_CONFIG_NAME_SERVER = "kenaito.config-center.server";
|
private static final String DEFAULT_CONFIG_NAME_SERVER = "kenaito.config-center.server";
|
||||||
|
|
||||||
/** 默认配置项:配置中心服务端口 */
|
/**
|
||||||
|
* 默认配置项:配置中心服务端口
|
||||||
|
*/
|
||||||
private static final String DEFAULT_CONFIG_NAME_PORT = "kenaito.config-center.port";
|
private static final String DEFAULT_CONFIG_NAME_PORT = "kenaito.config-center.port";
|
||||||
|
|
||||||
/** 默认配置项:将拉取的配置环境 */
|
/**
|
||||||
|
* 默认配置项:将拉取的配置环境
|
||||||
|
*/
|
||||||
private static final String DEFAULT_CONFIG_NAME_ENV = "kenaito.config-center.env";
|
private static final String DEFAULT_CONFIG_NAME_ENV = "kenaito.config-center.env";
|
||||||
|
|
||||||
/** 默认配置项:将拉取配置的应用的名称 */
|
/**
|
||||||
|
* 默认配置项:将拉取配置的应用的名称
|
||||||
|
*/
|
||||||
private static final String DEFAULT_CONFIG_NAME_DATA_ID = "kenaito.config-center.data-id";
|
private static final String DEFAULT_CONFIG_NAME_DATA_ID = "kenaito.config-center.data-id";
|
||||||
|
|
||||||
/** 默认配置项:配置缓存目录 */
|
/**
|
||||||
|
* 默认配置项:配置缓存目录
|
||||||
|
*/
|
||||||
private static final String DEFAULT_CONFIG_NAME_CACHE_DIR = "kenaito.config-center.cache-dir";
|
private static final String DEFAULT_CONFIG_NAME_CACHE_DIR = "kenaito.config-center.cache-dir";
|
||||||
|
|
||||||
/** Win路径分割符 */
|
/**
|
||||||
|
* Win路径分割符
|
||||||
|
*/
|
||||||
private static final String DEFAULT_PATH_SEP_WIN = "\\";
|
private static final String DEFAULT_PATH_SEP_WIN = "\\";
|
||||||
|
|
||||||
/** Mac路径分割符 */
|
/**
|
||||||
|
* Mac路径分割符
|
||||||
|
*/
|
||||||
private static final String DEFAULT_PATH_SEP_MAC = "/";
|
private static final String DEFAULT_PATH_SEP_MAC = "/";
|
||||||
|
|
||||||
/** 配置源名称 */
|
/**
|
||||||
|
* 配置源名称
|
||||||
|
*/
|
||||||
public static final String PROPERTY_SOURCE_NAME = "kenaito-dynamic-config";
|
public static final String PROPERTY_SOURCE_NAME = "kenaito-dynamic-config";
|
||||||
|
|
||||||
/** 当前客户端配置 */
|
/**
|
||||||
|
* 当前客户端配置
|
||||||
|
*/
|
||||||
public static final ClientInfo clientInfo = new ClientInfo();
|
public static final ClientInfo clientInfo = new ClientInfo();
|
||||||
|
|
||||||
/** 配置是否加载完毕 */
|
/**
|
||||||
|
* 配置是否加载完毕
|
||||||
|
*/
|
||||||
public static boolean isConfigLoaded = false;
|
public static boolean isConfigLoaded = false;
|
||||||
|
|
||||||
/** 服务器是否离线 */
|
/**
|
||||||
|
* 服务器是否离线
|
||||||
|
*/
|
||||||
public static boolean isServerOffline = false;
|
public static boolean isServerOffline = false;
|
||||||
|
|
||||||
/** 原有的配置信息:filename -> file content */
|
/**
|
||||||
|
* 原有的配置信息:filename -> file content
|
||||||
|
*/
|
||||||
public static Map<String, String> originConfigs = new HashMap<>();
|
public static Map<String, String> originConfigs = new HashMap<>();
|
||||||
|
|
||||||
/** 转换后的配置信息:filename -> {configKey: configValue} */
|
/**
|
||||||
|
* 转换后的配置信息:filename -> {configKey: configValue}
|
||||||
|
*/
|
||||||
public static Map<String, Map<String, Object>> lastConfigs = new HashMap<>();
|
public static Map<String, Map<String, Object>> lastConfigs = new HashMap<>();
|
||||||
|
|
||||||
/** 所有自定义配置项缓存 */
|
/**
|
||||||
|
* 所有自定义配置项缓存
|
||||||
|
*/
|
||||||
public static Map<String, Object> cacheConfigs = new HashMap<>();
|
public static Map<String, Object> cacheConfigs = new HashMap<>();
|
||||||
|
|
||||||
/** 定时将配置写盘,缓存配置信息 */
|
/**
|
||||||
|
* 定时将配置写盘,缓存配置信息
|
||||||
|
*/
|
||||||
private final Thread fixedTimeFlushConfigFileThread =
|
private final Thread fixedTimeFlushConfigFileThread =
|
||||||
ThreadUtil.newThread(
|
ThreadUtil.newThread(
|
||||||
() -> {
|
() -> {
|
||||||
|
@ -257,7 +290,9 @@ public class ClientConfigLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建缓存文件夹 */
|
/**
|
||||||
|
* 创建缓存文件夹
|
||||||
|
*/
|
||||||
private static void createCacheDir(String cacheDir) {
|
private static void createCacheDir(String cacheDir) {
|
||||||
Path path = Paths.get(cacheDir);
|
Path path = Paths.get(cacheDir);
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
package cn.odboy.config.context;
|
package cn.odboy.config.context;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import java.util.Map;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.cloud.context.refresh.ConfigDataContextRefresher;
|
//import org.springframework.cloud.context.refresh.ConfigDataContextRefresher;
|
||||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.springframework.core.env.MutablePropertySources;
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端配置 辅助类
|
* 客户端配置 辅助类
|
||||||
|
* <p>
|
||||||
|
* 依赖 spring-cloud-context
|
||||||
*
|
*
|
||||||
* @author odboy
|
* @author odboy
|
||||||
* @date 2024-12-07
|
* @date 2024-12-07
|
||||||
|
@ -22,7 +24,8 @@ import org.springframework.stereotype.Component;
|
||||||
public class ClientPropertyHelper {
|
public class ClientPropertyHelper {
|
||||||
private final ConfigurableEnvironment environment;
|
private final ConfigurableEnvironment environment;
|
||||||
private final ValueAnnotationProcessor valueAnnotationProcessor;
|
private final ValueAnnotationProcessor valueAnnotationProcessor;
|
||||||
private final ConfigDataContextRefresher configDataContextRefresher;
|
// private final ConfigDataContextRefresher configDataContextRefresher;
|
||||||
|
private final ConfigPropertyContextRefresher contextRefresher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态更新配置值
|
* 动态更新配置值
|
||||||
|
@ -36,8 +39,7 @@ public class ClientPropertyHelper {
|
||||||
MutablePropertySources propertySources = environment.getPropertySources();
|
MutablePropertySources propertySources = environment.getPropertySources();
|
||||||
if (propertySources.contains(ClientConfigLoader.PROPERTY_SOURCE_NAME)) {
|
if (propertySources.contains(ClientConfigLoader.PROPERTY_SOURCE_NAME)) {
|
||||||
// 更新属性值
|
// 更新属性值
|
||||||
PropertySource<?> propertySource =
|
PropertySource<?> propertySource = propertySources.get(ClientConfigLoader.PROPERTY_SOURCE_NAME);
|
||||||
propertySources.get(ClientConfigLoader.PROPERTY_SOURCE_NAME);
|
|
||||||
Map<String, Object> source = ((MapPropertySource) propertySource).getSource();
|
Map<String, Object> source = ((MapPropertySource) propertySource).getSource();
|
||||||
source.put(propertyName, value);
|
source.put(propertyName, value);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +48,8 @@ public class ClientPropertyHelper {
|
||||||
// 刷新上下文(解决 @ConfigurationProperties注解的类属性值更新 问题)
|
// 刷新上下文(解决 @ConfigurationProperties注解的类属性值更新 问题)
|
||||||
// Spring Cloud只会对被@RefreshScope和@ConfigurationProperties标注的bean进行刷新
|
// Spring Cloud只会对被@RefreshScope和@ConfigurationProperties标注的bean进行刷新
|
||||||
// 这个方法主要做了两件事:刷新配置源,也就是PropertySource,然后刷新了@ConfigurationProperties注解的类
|
// 这个方法主要做了两件事:刷新配置源,也就是PropertySource,然后刷新了@ConfigurationProperties注解的类
|
||||||
configDataContextRefresher.refresh();
|
// configDataContextRefresher.refresh();
|
||||||
|
contextRefresher.refreshAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package cn.odboy.config.context;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置属性上下文 刷新
|
||||||
|
*
|
||||||
|
* @author odboy
|
||||||
|
* @date 2024-12-07
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ConfigPropertyContextRefresher {
|
||||||
|
private final ConfigurationPropertiesAnnotationProcessor processor;
|
||||||
|
private final ConfigurableEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新单个属性
|
||||||
|
*
|
||||||
|
* @param propertyName 属性名表达式
|
||||||
|
* @param value 属性值
|
||||||
|
*/
|
||||||
|
public void refreshSingle(String propertyName, Object value) {
|
||||||
|
MutablePropertySources propertySources = environment.getPropertySources();
|
||||||
|
if (propertySources.contains(ClientConfigLoader.PROPERTY_SOURCE_NAME)) {
|
||||||
|
// 更新属性值
|
||||||
|
PropertySource<?> propertySource = propertySources.get(ClientConfigLoader.PROPERTY_SOURCE_NAME);
|
||||||
|
Map<String, Object> source = ((MapPropertySource) propertySource).getSource();
|
||||||
|
source.put(propertyName, value);
|
||||||
|
} else {
|
||||||
|
// 新增属性值
|
||||||
|
Map<String, Object> propertyMap = new HashMap<>(1);
|
||||||
|
MapPropertySource propertySource = new MapPropertySource(ClientConfigLoader.PROPERTY_SOURCE_NAME, propertyMap);
|
||||||
|
propertySources.addFirst(propertySource);
|
||||||
|
}
|
||||||
|
// 使用 Binder 重新绑定 @ConfigurationProperties
|
||||||
|
Binder binder = Binder.get(environment);
|
||||||
|
for (Map.Entry<String, Object> propertyPrefixBean : processor.getPrefixBeanMap().entrySet()) {
|
||||||
|
binder.bind(propertyPrefixBean.getKey(), Bindable.ofInstance(propertyPrefixBean.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新所有属性
|
||||||
|
*/
|
||||||
|
public void refreshAll() {
|
||||||
|
MutablePropertySources propertySources = environment.getPropertySources();
|
||||||
|
if (propertySources.contains(ClientConfigLoader.PROPERTY_SOURCE_NAME)) {
|
||||||
|
// 替换属性值
|
||||||
|
MapPropertySource propertySource = new MapPropertySource(ClientConfigLoader.PROPERTY_SOURCE_NAME, ClientConfigLoader.cacheConfigs);
|
||||||
|
propertySources.replace(ClientConfigLoader.PROPERTY_SOURCE_NAME, propertySource);
|
||||||
|
} else {
|
||||||
|
// 新增属性值
|
||||||
|
Map<String, Object> propertyMap = new HashMap<>(1);
|
||||||
|
MapPropertySource propertySource = new MapPropertySource(ClientConfigLoader.PROPERTY_SOURCE_NAME, propertyMap);
|
||||||
|
propertySources.addFirst(propertySource);
|
||||||
|
}
|
||||||
|
// 使用 Binder 重新绑定 @ConfigurationProperties
|
||||||
|
Binder binder = Binder.get(environment);
|
||||||
|
for (Map.Entry<String, Object> propertyPrefixBean : processor.getPrefixBeanMap().entrySet()) {
|
||||||
|
binder.bind(propertyPrefixBean.getKey(), Bindable.ofInstance(propertyPrefixBean.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package cn.odboy.config.context;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载并处理@ConfigurationProperties对应的引用
|
||||||
|
*
|
||||||
|
* @author odboy
|
||||||
|
* @date 2024-12-07
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ConfigurationPropertiesAnnotationProcessor implements BeanPostProcessor {
|
||||||
|
private final Logger logger =
|
||||||
|
LoggerFactory.getLogger(ConfigurationPropertiesAnnotationProcessor.class);
|
||||||
|
@Getter
|
||||||
|
private final Map<String, Object> prefixBeanMap = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
Class<?> clazz = bean.getClass();
|
||||||
|
while (clazz != null) {
|
||||||
|
if (clazz.isAnnotationPresent(ConfigurationProperties.class)) {
|
||||||
|
// 排除springboot框架的配置
|
||||||
|
if (beanName.contains("springframework")) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 排除数据源框架的配置
|
||||||
|
if (beanName.contains("dataSource") || beanName.contains("druid")) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 排除ORM框架的配置
|
||||||
|
if (beanName.contains("mybatis")) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 排除ip2region的配置
|
||||||
|
if (beanName.contains("ip2region")) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
logger.info("扫描到自定义的@ConfigurationProperties注解类: {}", beanName);
|
||||||
|
this.processConfigBean(clazz, bean);
|
||||||
|
}
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processConfigBean(Class<?> clazz, Object bean) {
|
||||||
|
ConfigurationProperties annotation = clazz.getAnnotation(ConfigurationProperties.class);
|
||||||
|
// 比如: kenaito.config-center
|
||||||
|
prefixBeanMap.put(annotation.prefix(), bean);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
package cn.odboy.config.context;
|
package cn.odboy.config.context;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
|
@ -10,6 +7,10 @@ import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载并处理@Value对应的引用
|
* 加载并处理@Value对应的引用
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,11 +6,12 @@ import io.netty.channel.*;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置中心客户端
|
* 配置中心客户端
|
||||||
*
|
*
|
||||||
|
@ -21,37 +22,60 @@ import org.slf4j.LoggerFactory;
|
||||||
public class ConfigClient {
|
public class ConfigClient {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConfigClient.class);
|
private static final Logger logger = LoggerFactory.getLogger(ConfigClient.class);
|
||||||
|
|
||||||
/** 客户端 */
|
/**
|
||||||
|
* 客户端
|
||||||
|
*/
|
||||||
private EventLoopGroup eventLoopGroup;
|
private EventLoopGroup eventLoopGroup;
|
||||||
|
|
||||||
/** 存放客户端bootstrap对象 */
|
/**
|
||||||
|
* 存放客户端bootstrap对象
|
||||||
|
*/
|
||||||
private Bootstrap bootstrap;
|
private Bootstrap bootstrap;
|
||||||
|
|
||||||
/** 存放客户端channel对象 */
|
/**
|
||||||
|
* 存放客户端channel对象
|
||||||
|
*/
|
||||||
private Channel channel;
|
private Channel channel;
|
||||||
|
|
||||||
/** 重连间隔,单位秒 */
|
/**
|
||||||
|
* 重连间隔,单位秒
|
||||||
|
*/
|
||||||
private Integer delaySeconds = 5;
|
private Integer delaySeconds = 5;
|
||||||
|
|
||||||
/** 连接属性:服务ip */
|
/**
|
||||||
|
* 连接属性:服务ip
|
||||||
|
*/
|
||||||
private String serverIp;
|
private String serverIp;
|
||||||
|
|
||||||
/** 连接属性:服务端口 */
|
/**
|
||||||
|
* 连接属性:服务端口
|
||||||
|
*/
|
||||||
private Integer serverPort;
|
private Integer serverPort;
|
||||||
|
|
||||||
/** 私有静态实例 */
|
/**
|
||||||
|
* 私有静态实例
|
||||||
|
*/
|
||||||
private static volatile ConfigClient instance;
|
private static volatile ConfigClient instance;
|
||||||
|
|
||||||
/** 最大重试次数 */
|
/**
|
||||||
|
* 最大重试次数
|
||||||
|
*/
|
||||||
private static final int MAX_RETRY_COUNT = 2;
|
private static final int MAX_RETRY_COUNT = 2;
|
||||||
|
|
||||||
/** 当前重试次数 */
|
/**
|
||||||
|
* 当前重试次数
|
||||||
|
*/
|
||||||
private static int retryCount = 0;
|
private static int retryCount = 0;
|
||||||
|
|
||||||
/** 私有化构造函数 */
|
/**
|
||||||
private ConfigClient() {}
|
* 私有化构造函数
|
||||||
|
*/
|
||||||
|
private ConfigClient() {
|
||||||
|
}
|
||||||
|
|
||||||
/** 获取 */
|
/**
|
||||||
|
* 获取
|
||||||
|
*/
|
||||||
public static ConfigClient getInstance() {
|
public static ConfigClient getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
synchronized (ConfigClient.class) {
|
synchronized (ConfigClient.class) {
|
||||||
|
@ -99,7 +123,9 @@ public class ConfigClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ConfigClientChannelListener implements ChannelFutureListener {
|
private class ConfigClientChannelListener implements ChannelFutureListener {
|
||||||
/** 该方法会在channelActive之前执行,去判断客户端连接是否成功,并做失败重连的操作 */
|
/**
|
||||||
|
* 该方法会在channelActive之前执行,去判断客户端连接是否成功,并做失败重连的操作
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(ChannelFuture channelFuture) throws Exception {
|
public void operationComplete(ChannelFuture channelFuture) throws Exception {
|
||||||
// 连接成功后保存Channel
|
// 连接成功后保存Channel
|
||||||
|
@ -130,7 +156,9 @@ public class ConfigClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重新连接 */
|
/**
|
||||||
|
* 重新连接
|
||||||
|
*/
|
||||||
protected void reConnect() {
|
protected void reConnect() {
|
||||||
try {
|
try {
|
||||||
logger.info("重连配置中心服务 {}:{}", this.serverIp, this.serverPort);
|
logger.info("重连配置中心服务 {}:{}", this.serverIp, this.serverPort);
|
||||||
|
|
|
@ -9,14 +9,15 @@ import cn.odboy.config.model.msgtype.ConfigFileInfo;
|
||||||
import cn.odboy.config.util.MessageUtil;
|
import cn.odboy.config.util.MessageUtil;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置中心客户端 业务处理
|
* 配置中心客户端 业务处理
|
||||||
|
|
Loading…
Reference in New Issue