change: 日常小调整.
This commit is contained in:
@@ -18,13 +18,13 @@ public final class ManagerLite {
|
||||
init();
|
||||
}
|
||||
|
||||
private static SystemInitializer init() {
|
||||
private static void init() {
|
||||
SystemInitializer systemInitializer = SystemInitializer
|
||||
.configurer()
|
||||
.clearCache(false)
|
||||
.configuration(new PropertiesConfiguration(SystemConstants.USER_SETTINGS_PROPERTIES_PATH))
|
||||
.instanceContext(new FileInstanceContext())
|
||||
.done();
|
||||
systemInitializer.refresh();
|
||||
return systemInitializer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.serliunx.ddns.support.feign.client;
|
||||
package com.serliunx.ddns.client;
|
||||
|
||||
import com.serliunx.ddns.client.entity.IPAddressResponse;
|
||||
import com.serliunx.ddns.support.feign.JacksonDecoder;
|
||||
import com.serliunx.ddns.support.feign.JacksonEncoder;
|
||||
import com.serliunx.ddns.support.feign.client.entity.IPAddressResponse;
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.RequestLine;
|
||||
@@ -27,7 +27,7 @@ public interface IPAddressClient {
|
||||
* @return IPAddressResponse
|
||||
*/
|
||||
@RequestLine("GET /json")
|
||||
IPAddressResponse getIPAddress();
|
||||
IPAddressResponse getIPAddress();
|
||||
|
||||
static IPAddressClient getInstance() {
|
||||
return Feign.builder()
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.serliunx.ddns.support.feign.client.entity;
|
||||
package com.serliunx.ddns.client.entity;
|
||||
|
||||
/**
|
||||
* IP地址查询响应
|
||||
@@ -14,15 +14,15 @@ import java.util.Map;
|
||||
* @since 2024/5/15
|
||||
*/
|
||||
public final class InstanceClasses {
|
||||
|
||||
private InstanceClasses(){throw new UnsupportedOperationException();}
|
||||
|
||||
private static final Map<InstanceType, Class<? extends Instance>> instanceTypeMap =
|
||||
new HashMap<InstanceType, Class<? extends Instance>>() {
|
||||
{
|
||||
put(InstanceType.ALI_YUN, AliyunInstance.class);
|
||||
put(InstanceType.TENCENT_CLOUD, TencentInstance.class);
|
||||
}
|
||||
};
|
||||
private static final Map<InstanceType, Class<? extends Instance>> instanceTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
instanceTypeMap.put(InstanceType.ALI_YUN, AliyunInstance.class);
|
||||
instanceTypeMap.put(InstanceType.TENCENT_CLOUD, TencentInstance.class);
|
||||
}
|
||||
|
||||
public static Class<? extends Instance> match(InstanceType type) {
|
||||
return instanceTypeMap.get(type);
|
||||
|
||||
@@ -25,7 +25,7 @@ import static com.serliunx.ddns.util.InstanceUtils.validateInstance;
|
||||
*/
|
||||
public abstract class AbstractInstanceContext implements InstanceContext, MultipleSourceInstanceContext {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractInstanceContext.class);
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final Set<ListableInstanceFactory> listableInstanceFactories = new HashSet<>();
|
||||
|
||||
@@ -63,9 +63,7 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
|
||||
Set<Instance> instances = new HashSet<>();
|
||||
|
||||
// 高优先级的实例工厂会覆盖低优先级实例工厂所加载的实例
|
||||
listableInstanceFactories.stream()
|
||||
.sorted()
|
||||
.forEach(f -> instances.addAll(f.getInstances()));
|
||||
getSortedListableInstanceFactories().forEach(f -> instances.addAll(f.getInstances()));
|
||||
|
||||
// 初次载入
|
||||
cacheInstanceMap = new HashMap<>(instances.stream().collect(Collectors.toMap(Instance::getName, i -> i)));
|
||||
@@ -86,10 +84,11 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
|
||||
instanceLock.lock();
|
||||
String name = instance.getName();
|
||||
Instance instanceExists = instanceMap.get(name);
|
||||
if (instanceExists != null)
|
||||
if (instanceExists != null) {
|
||||
throw new InstanceExistsException("该实例已存在!", name, instanceExists);
|
||||
else
|
||||
} else {
|
||||
instanceMap.put(name, instance);
|
||||
}
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e);
|
||||
}finally {
|
||||
@@ -146,7 +145,7 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
|
||||
protected void clearCache() {
|
||||
if (cacheInstanceMap != null
|
||||
&& !cacheInstanceMap.isEmpty()){
|
||||
int size = cacheInstanceMap.size();
|
||||
final int size = cacheInstanceMap.size();
|
||||
cacheInstanceMap.clear();
|
||||
// 清理实例工厂的缓存信息
|
||||
listableInstanceFactories.forEach(Clearable::clear);
|
||||
|
||||
@@ -3,7 +3,10 @@ package com.serliunx.ddns.core.context;
|
||||
import com.serliunx.ddns.core.factory.InstanceFactory;
|
||||
import com.serliunx.ddns.core.factory.ListableInstanceFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 多数据源的实例容器, 将多种实例来源汇聚到一起
|
||||
@@ -26,4 +29,18 @@ public interface MultipleSourceInstanceContext extends InstanceContext, Listable
|
||||
* @return 实例工厂列表
|
||||
*/
|
||||
Set<ListableInstanceFactory> getListableInstanceFactories();
|
||||
|
||||
/**
|
||||
* 获取当前实例容器下所有实例工厂(已排序)
|
||||
* @return 已排序的实例工厂
|
||||
*/
|
||||
default List<ListableInstanceFactory> getSortedListableInstanceFactories() {
|
||||
Set<ListableInstanceFactory> listableInstanceFactories = getListableInstanceFactories();
|
||||
if (listableInstanceFactories == null || listableInstanceFactories.isEmpty())
|
||||
return Collections.emptyList();
|
||||
|
||||
return listableInstanceFactories.stream()
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,11 @@ public abstract class AbstractInstanceFactory implements InstanceFactory, Listab
|
||||
clear0();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(priority: " + getPriority() + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* 交由子类去加载实例信息
|
||||
* @return 实例信息
|
||||
|
||||
@@ -26,6 +26,16 @@ public abstract class FileInstanceFactory extends AbstractInstanceFactory {
|
||||
this.instanceDir = instanceDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 256;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(instanceDir: " + instanceDir + ", priority: " + getPriority() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Instance> load() {
|
||||
Set<File> files = loadFiles();
|
||||
@@ -38,11 +48,6 @@ public abstract class FileInstanceFactory extends AbstractInstanceFactory {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交由具体的子类去加载实例, 比如: json格式的实例信息、xml格式的实例信息
|
||||
* @param file 文件信息
|
||||
|
||||
@@ -96,12 +96,14 @@ public class YamlFileInstanceFactory extends FileInstanceFactory {
|
||||
f.set(instance, Enum.valueOf((Class<? extends Enum>) clazz, (String) value));
|
||||
continue;
|
||||
}
|
||||
if (value != null)
|
||||
if (value != null) {
|
||||
f.set(instance, value);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
f.setAccessible(false);
|
||||
}
|
||||
f.setAccessible(false);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import static com.serliunx.ddns.constant.SystemConstants.XML_ROOT_INSTANCE_NAME;
|
||||
@JacksonXmlRootElement(localName = XML_ROOT_INSTANCE_NAME)
|
||||
public abstract class AbstractInstance implements Instance {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractInstance.class);
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 实例名称
|
||||
|
||||
@@ -14,6 +14,7 @@ public final class Configurer {
|
||||
|
||||
private Configuration configuration;
|
||||
private MultipleSourceInstanceContext instanceContext;
|
||||
private boolean clearCache;
|
||||
|
||||
Configurer(){}
|
||||
|
||||
@@ -29,8 +30,13 @@ public final class Configurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Configurer clearCache(boolean clearCache) {
|
||||
this.clearCache = clearCache;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SystemInitializer done() {
|
||||
Assert.notNull(configuration, instanceContext);
|
||||
return new SystemInitializer(configuration, instanceContext);
|
||||
return new SystemInitializer(configuration, instanceContext, clearCache);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,9 @@ public final class NetworkContextHolder {
|
||||
}
|
||||
|
||||
public static String getIpAddress() {
|
||||
if(IP_ADDRESS != null)
|
||||
if(IP_ADDRESS != null) {
|
||||
return IP_ADDRESS;
|
||||
}
|
||||
try {
|
||||
if(!IP_CONTEXT_WAIT_LATCH.await(IP_CONTEXT_TIME_OUT, TimeUnit.SECONDS)) {
|
||||
log.error("IP地址获取超时.");
|
||||
|
||||
@@ -6,8 +6,8 @@ import com.serliunx.ddns.core.Clearable;
|
||||
import com.serliunx.ddns.core.Refreshable;
|
||||
import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
|
||||
import com.serliunx.ddns.core.instance.Instance;
|
||||
import com.serliunx.ddns.support.feign.client.IPAddressClient;
|
||||
import com.serliunx.ddns.support.feign.client.entity.IPAddressResponse;
|
||||
import com.serliunx.ddns.client.IPAddressClient;
|
||||
import com.serliunx.ddns.client.entity.IPAddressResponse;
|
||||
import com.serliunx.ddns.thread.TaskThreadFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -40,14 +40,20 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
|
||||
private final Configuration configuration;
|
||||
private final MultipleSourceInstanceContext instanceContext;
|
||||
private final boolean clearCache;
|
||||
|
||||
private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
|
||||
private Set<Instance> instances;
|
||||
private final Map<String, ScheduledFuture<?>> runningInstances = new HashMap<>(64);
|
||||
|
||||
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext) {
|
||||
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext, boolean clearCache) {
|
||||
this.configuration = configuration;
|
||||
this.instanceContext = instanceContext;
|
||||
this.clearCache = clearCache;
|
||||
}
|
||||
|
||||
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext) {
|
||||
this(configuration, instanceContext, true);
|
||||
}
|
||||
|
||||
public static Configurer configurer() {
|
||||
@@ -80,8 +86,10 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
// 运行实例
|
||||
runInstances();
|
||||
|
||||
// 实例提交后, 清理实例、配置缓存, 因为读取一次就不需要了
|
||||
clear();
|
||||
// 清理实例、配置缓存, 正常情况下读取一次就不需要了
|
||||
if (clearCache) {
|
||||
clear();
|
||||
}
|
||||
log.info("初始化完成!");
|
||||
InstanceContextHolder.clearAdditional();
|
||||
}
|
||||
@@ -120,8 +128,9 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
if (inputStream != null) {
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1)
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
outputStream.close();
|
||||
} catch (Exception e) {
|
||||
@@ -140,7 +149,7 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
}
|
||||
// 初始化实例
|
||||
i.refresh();
|
||||
ScheduledFuture<?> future = scheduledThreadPoolExecutor.scheduleWithFixedDelay(i, 0,
|
||||
ScheduledFuture<?> future = scheduledThreadPoolExecutor.scheduleWithFixedDelay(i, 5,
|
||||
i.getInterval(), TimeUnit.SECONDS);
|
||||
runningInstances.put(i.getName(), future);
|
||||
log.info("{}({})已启动, 运行周期 {} 秒.", i.getName(), i.getType(), i.getInterval());
|
||||
@@ -187,15 +196,15 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
boolean result = scheduledThreadPoolExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
if (result) {
|
||||
log.error("线程池无法在正常的时间范围内关闭, 将强制关闭线程池!");
|
||||
if (!scheduledThreadPoolExecutor.isShutdown())
|
||||
if (!scheduledThreadPoolExecutor.isShutdown()) {
|
||||
scheduledThreadPoolExecutor.shutdownNow();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
instances.clear();
|
||||
|
||||
runningInstances.clear();
|
||||
} finally {
|
||||
instances.clear();
|
||||
runningInstances.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user