Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a729a5d99c | |||
|
|
d0e1792e4b | ||
| fe86653903 | |||
| eefd907866 | |||
| f70db6ef90 | |||
| d929975809 |
12
pom.xml
12
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.serliunx.ddns</groupId>
|
||||
<artifactId>ddns-manager-lite</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.3-alpha</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
@@ -19,6 +19,8 @@
|
||||
<snakeyaml.version>1.30</snakeyaml.version>
|
||||
<aliyundns.sdk.version>3.0.14</aliyundns.sdk.version>
|
||||
<tencent.dnspod.sdk.version>3.1.1002</tencent.dnspod.sdk.version>
|
||||
<junit.version>4.13.2</junit.version>
|
||||
<sqlite.jdbc.version>3.47.0.0</sqlite.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -55,9 +57,15 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- sqlite-jdbc -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>${sqlite.jdbc.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -35,4 +35,9 @@ public final class ConfigurationKeys {
|
||||
* http请求超时时间(秒)
|
||||
*/
|
||||
public static final String KEY_HTTP_OVERTIME = "system.http.overtime";
|
||||
|
||||
/**
|
||||
* ip地址提供器类型
|
||||
*/
|
||||
public static final String KEY_IP_PROVIDER_TYPE = "system.ip.provider.type";
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* yml/yaml格式的配置文件,目前用于语言文件
|
||||
* TODO 待重构
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.0
|
||||
* @since 2024/6/17
|
||||
*/
|
||||
@Deprecated
|
||||
public class YamlConfiguration extends FileConfiguration {
|
||||
|
||||
public YamlConfiguration(String path, boolean refresh) {
|
||||
|
||||
32
src/main/java/com/serliunx/ddns/constant/IpProviderType.java
Normal file
32
src/main/java/com/serliunx/ddns/constant/IpProviderType.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.serliunx.ddns.constant;
|
||||
|
||||
import com.serliunx.ddns.support.ipprovider.IpApiProvider;
|
||||
import com.serliunx.ddns.support.ipprovider.Provider;
|
||||
|
||||
/**
|
||||
* ip供应器类型
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public enum IpProviderType {
|
||||
|
||||
/**
|
||||
* ip数据提供商 <a href="https://ip-api.com/">ip-api</a>
|
||||
* <li> 国外的数据, 国内访问不稳定.
|
||||
*/
|
||||
IP_API(new IpApiProvider()),
|
||||
|
||||
;
|
||||
|
||||
private final Provider provider;
|
||||
|
||||
IpProviderType(Provider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public Provider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
@@ -82,4 +82,9 @@ public final class SystemConstants {
|
||||
* 用户目录下的.yml配置文件
|
||||
*/
|
||||
public static final String USER_SETTINGS_YAML_PATH = USER_DIR + File.separator + CONFIG_YAML_FILE;
|
||||
|
||||
/**
|
||||
* 程序数据库
|
||||
*/
|
||||
public static final String SQLITE_URL = "jdbc:sqlite:data.db";
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ public abstract class AbstractInstanceFactory implements InstanceFactory, Listab
|
||||
|
||||
@Override
|
||||
public Map<String, Instance> getInstanceOfType(InstanceType type) {
|
||||
Assert.notNull(instanceMap);
|
||||
if (instanceMap == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return instanceMap.values()
|
||||
.stream()
|
||||
.filter(i -> i.getType().equals(type))
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.serliunx.ddns.core.factory;
|
||||
|
||||
import com.serliunx.ddns.core.instance.Instance;
|
||||
import com.serliunx.ddns.support.Assert;
|
||||
import com.serliunx.ddns.support.sqlite.SQLiteConnector;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 数据库示例工厂: 从数据库中(sqlite)存储、加载示例信息
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/20
|
||||
*/
|
||||
public final class DatabaseInstanceFactory extends AbstractInstanceFactory implements PersistentInstanceFactory {
|
||||
|
||||
private final SQLiteConnector connector;
|
||||
|
||||
public DatabaseInstanceFactory(SQLiteConnector connector) {
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Instance> load() {
|
||||
Assert.notNull(connector, "数据库连接不能为空!");
|
||||
connector.refresh();
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(Instance instance) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.serliunx.ddns.core.factory;
|
||||
|
||||
import com.serliunx.ddns.core.instance.Instance;
|
||||
|
||||
/**
|
||||
* 可持久化的实例工厂, 支持编辑、保存实例数据.
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/20
|
||||
*/
|
||||
public interface PersistentInstanceFactory extends InstanceFactory {
|
||||
|
||||
/**
|
||||
* 保存实例信息
|
||||
*
|
||||
* @param instance 实例
|
||||
* @return 成功保存返回真, 否则返回假.
|
||||
*/
|
||||
boolean save(Instance instance);
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public final class Assert {
|
||||
}
|
||||
|
||||
public static void notNull(Object object, String msg) {
|
||||
if(object == null) {
|
||||
if (object == null) {
|
||||
throw new NullPointerException(msg);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,12 @@ public final class Assert {
|
||||
}
|
||||
|
||||
public static void isLargerThan(int source, int target) {
|
||||
if (source <= target) {
|
||||
throw new IllegalArgumentException(String.format("%s太小了, 它必须大于%s", source, target));
|
||||
}
|
||||
}
|
||||
|
||||
public static void isLargerThan(long source, long target) {
|
||||
if(source <= target) {
|
||||
throw new IllegalArgumentException(String.format("%s太小了, 它必须大于%s", source, target));
|
||||
}
|
||||
@@ -43,13 +49,13 @@ public final class Assert {
|
||||
|
||||
public static void notEmpty(Collection<?> collection) {
|
||||
notNull(collection);
|
||||
if(collection.isEmpty())
|
||||
if (collection.isEmpty())
|
||||
throw new IllegalArgumentException("参数不能为空!");
|
||||
}
|
||||
|
||||
public static void notEmpty(CharSequence charSequence) {
|
||||
notNull(charSequence);
|
||||
if(charSequence.length() == 0)
|
||||
if (charSequence.length() == 0)
|
||||
throw new IllegalArgumentException("参数不能为空!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.serliunx.ddns.support;
|
||||
|
||||
import com.serliunx.ddns.config.Configuration;
|
||||
import com.serliunx.ddns.config.ConfigurationKeys;
|
||||
import com.serliunx.ddns.constant.IpProviderType;
|
||||
import com.serliunx.ddns.constant.SystemConstants;
|
||||
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.ipprovider.IpApiProvider;
|
||||
import com.serliunx.ddns.support.ipprovider.Provider;
|
||||
import com.serliunx.ddns.support.ipprovider.ScheduledProvider;
|
||||
import com.serliunx.ddns.support.okhttp.IPAddressResponse;
|
||||
import com.serliunx.ddns.support.okhttp.HttpClient;
|
||||
import com.serliunx.ddns.thread.TaskThreadFactory;
|
||||
@@ -46,6 +51,7 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
|
||||
private Set<Instance> instances;
|
||||
private final Map<String, ScheduledFuture<?>> runningInstances = new HashMap<>(64);
|
||||
private ScheduledProvider scheduledProvider;
|
||||
|
||||
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext, boolean clearCache) {
|
||||
this.configuration = configuration;
|
||||
@@ -79,6 +85,9 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
// 获取核心线程数量, 默认为CPU核心数量
|
||||
int coreSize = configuration.getInteger(KEY_THREAD_POOL_CORE_SIZE, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
// 初始化ip地址更新任务
|
||||
initIpTask();
|
||||
|
||||
// 初始化线程池
|
||||
initThreadPool(coreSize);
|
||||
|
||||
@@ -165,20 +174,6 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
// 初始化一个线程保活
|
||||
scheduledThreadPoolExecutor.submit(() -> {});
|
||||
|
||||
// 提交定时获取网络IP的定时任务
|
||||
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
|
||||
InstanceContextHolder.setAdditional("ip-update");
|
||||
log.info("正在尝试获取本机最新的IP地址.");
|
||||
IPAddressResponse response = HttpClient.getIPAddress();
|
||||
String ip;
|
||||
if(response != null
|
||||
&& (ip = response.getQuery()) != null) {
|
||||
NetworkContextHolder.setIpAddress(ip);
|
||||
log.info("本机最新公网IP地址 => {}", ip);
|
||||
}
|
||||
InstanceContextHolder.clearAdditional();
|
||||
}, 0, configuration.getLong(KEY_TASK_REFRESH_INTERVAL_IP, 300L), TimeUnit.SECONDS);
|
||||
|
||||
// 添加进程结束钩子函数
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
InstanceContextHolder.setAdditional("stopping");
|
||||
@@ -189,6 +184,21 @@ public final class SystemInitializer implements Refreshable, Clearable {
|
||||
}, "DDNS-ShutDownHook"));
|
||||
}
|
||||
|
||||
private void initIpTask() {
|
||||
scheduledProvider = new ScheduledProvider(getInternalProvider(),
|
||||
configuration.getLong(KEY_TASK_REFRESH_INTERVAL_IP, 300L));
|
||||
|
||||
scheduledProvider.whenUpdate(ip -> {
|
||||
NetworkContextHolder.setIpAddress(ip);
|
||||
log.info("本机最新公网IP地址 => {}", ip);
|
||||
});
|
||||
}
|
||||
|
||||
private Provider getInternalProvider() {
|
||||
return configuration.getEnum(IpProviderType.class, ConfigurationKeys.KEY_IP_PROVIDER_TYPE,
|
||||
IpProviderType.IP_API).getProvider();
|
||||
}
|
||||
|
||||
private void checkAndCloseSafely() {
|
||||
if (scheduledThreadPoolExecutor == null)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.serliunx.ddns.support.ipprovider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 抽象的ip提供器, 定义公共逻辑
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public abstract class AbstractProvider implements Provider {
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* 运行期间总共的ip查询次数
|
||||
*/
|
||||
protected long total;
|
||||
/**
|
||||
* 上次发生的变动的ip地址
|
||||
*/
|
||||
protected String last = null;
|
||||
/**
|
||||
* 缓存的最新ip地址
|
||||
* <li> !!!该地址为上次获得最新地址, 不一定为当前最新的地址
|
||||
*/
|
||||
protected String cache = null;
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
//do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
String ipAddress = doGet();
|
||||
if (ipAddress == null) {
|
||||
log.error("ip地址获取失败!");
|
||||
return null;
|
||||
}
|
||||
total++;
|
||||
|
||||
if (cache == null ||
|
||||
!cache.equals(ipAddress)) {
|
||||
last = cache;
|
||||
cache = ipAddress;
|
||||
}
|
||||
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取具体的ip地址
|
||||
*/
|
||||
protected abstract String doGet();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.serliunx.ddns.support.ipprovider;
|
||||
|
||||
import com.serliunx.ddns.support.okhttp.HttpClient;
|
||||
import com.serliunx.ddns.support.okhttp.IPAddressResponse;
|
||||
|
||||
/**
|
||||
* ip数据提供商 <a href="https://ip-api.com/">ip-api</a>
|
||||
* <li> 国外的数据, 国内访问不稳定.
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public final class IpApiProvider extends AbstractProvider {
|
||||
|
||||
@Override
|
||||
protected String doGet() {
|
||||
IPAddressResponse response = HttpClient.getIPAddress();
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
return response.getQuery();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.serliunx.ddns.support.ipprovider;
|
||||
|
||||
/**
|
||||
* ip供应器接口定义
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public interface Provider {
|
||||
|
||||
/**
|
||||
* 获取本次运行期间ip的查询次数
|
||||
*
|
||||
* @return 查询次数
|
||||
*/
|
||||
long getCount();
|
||||
|
||||
/**
|
||||
* 获取上次发生变动的ip地址
|
||||
*
|
||||
* @return 上次发生变动的ip地址
|
||||
*/
|
||||
String getLast();
|
||||
|
||||
/**
|
||||
* 获取最新的ip
|
||||
*
|
||||
* @return 最新的ip
|
||||
*/
|
||||
String get();
|
||||
|
||||
/**
|
||||
* 获取缓存的最新ip地址
|
||||
* <li> !!!该地址为上次获得最新地址, 不一定为当前最新的地址
|
||||
*
|
||||
* @return 缓存的最新ip地址
|
||||
*/
|
||||
String getCache();
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
void init();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.serliunx.ddns.support.ipprovider;
|
||||
|
||||
import com.serliunx.ddns.support.Assert;
|
||||
import com.serliunx.ddns.support.InstanceContextHolder;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 自动更新的ip供应器
|
||||
* <li> 异步更新ip, 获取到的ip地址不一定为最新可用的。
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public class ScheduledProvider extends AbstractProvider {
|
||||
|
||||
private final Provider internalProvider;
|
||||
|
||||
/**
|
||||
* 执行周期(秒)
|
||||
*/
|
||||
private volatile long timePeriod;
|
||||
/**
|
||||
* 任务
|
||||
*/
|
||||
private volatile ScheduledFuture<?> task;
|
||||
|
||||
/**
|
||||
* 内置线程池
|
||||
*/
|
||||
private ScheduledThreadPoolExecutor poolExecutor = null;
|
||||
/**
|
||||
* 处理器
|
||||
*/
|
||||
private Consumer<String> valueConsumer = null;
|
||||
|
||||
public ScheduledProvider(Provider internalProvider, long timePeriod) {
|
||||
Assert.notNull(internalProvider);
|
||||
Assert.isLargerThan(timePeriod, 0);
|
||||
this.internalProvider = internalProvider;
|
||||
this.timePeriod = timePeriod;
|
||||
init();
|
||||
}
|
||||
|
||||
public ScheduledProvider(Provider internalProvider) {
|
||||
this(internalProvider, 60);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
poolExecutor = new ScheduledThreadPoolExecutor(2);
|
||||
// 提交
|
||||
submitTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新执行周期
|
||||
* <li> 回替换掉现有的更新任务
|
||||
*
|
||||
* @param timePeriod 新的执行周期
|
||||
*/
|
||||
public void changeTimePeriod(long timePeriod) {
|
||||
Assert.isLargerThan(timePeriod, 0);
|
||||
this.timePeriod = timePeriod;
|
||||
// 取消现有的任务
|
||||
task.cancel(true);
|
||||
submitTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* ip更新时需要执行的逻辑
|
||||
*
|
||||
* @param valueConsumer 逻辑
|
||||
*/
|
||||
public void whenUpdate(Consumer<String> valueConsumer) {
|
||||
this.valueConsumer = valueConsumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGet() {
|
||||
// 不应该执行到这里
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交任务逻辑
|
||||
*/
|
||||
private void submitTask() {
|
||||
task = poolExecutor.scheduleAtFixedRate(() -> {
|
||||
// 打断时, 终止已有的任务. (逻辑上不应该发生)
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
log.debug("上一个ip更新任务已终止.");
|
||||
return;
|
||||
}
|
||||
InstanceContextHolder.setAdditional("ip-update");
|
||||
cache = internalProvider.get();
|
||||
|
||||
if (valueConsumer != null) {
|
||||
valueConsumer.accept(cache);
|
||||
}
|
||||
}, 0, timePeriod, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,18 @@ public final class HttpClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpClient.class);
|
||||
private static final ObjectMapper JSON_MAPPER = new JsonMapper();
|
||||
private static final int DEFAULT_OVERTIME = 3;
|
||||
|
||||
private HttpClient() {throw new UnsupportedOperationException();}
|
||||
|
||||
static {
|
||||
CLIENT = new OkHttpClient.Builder()
|
||||
.connectTimeout(DEFAULT_OVERTIME, TimeUnit.SECONDS)
|
||||
.readTimeout(DEFAULT_OVERTIME, TimeUnit.SECONDS)
|
||||
.writeTimeout(DEFAULT_OVERTIME, TimeUnit.SECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本机的ip地址
|
||||
*
|
||||
@@ -63,7 +72,7 @@ public final class HttpClient {
|
||||
* @param configuration 配置信息
|
||||
*/
|
||||
public static void init(Configuration configuration) {
|
||||
Integer overtime = configuration.getInteger(ConfigurationKeys.KEY_HTTP_OVERTIME, 3);
|
||||
Integer overtime = configuration.getInteger(ConfigurationKeys.KEY_HTTP_OVERTIME, DEFAULT_OVERTIME);
|
||||
|
||||
CLIENT = new OkHttpClient.Builder()
|
||||
.connectTimeout(overtime, TimeUnit.SECONDS)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.serliunx.ddns.support.sqlite;
|
||||
|
||||
import com.serliunx.ddns.constant.SystemConstants;
|
||||
import com.serliunx.ddns.core.Refreshable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* SQLite 数据库连接
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/20
|
||||
*/
|
||||
public final class SQLiteConnector implements Refreshable {
|
||||
|
||||
private volatile Connection connection;
|
||||
|
||||
private final Lock initLock = new ReentrantLock();
|
||||
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SQLiteConnector.class);
|
||||
private static final SQLiteConnector INSTANCE = new SQLiteConnector();
|
||||
|
||||
// private-ctor
|
||||
private SQLiteConnector() {}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接初始化
|
||||
*/
|
||||
private void init() {
|
||||
if (initialized) {
|
||||
log.warn("sql connection already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!initLock.tryLock()) {
|
||||
log.error("sql connection already initialing");
|
||||
}
|
||||
|
||||
try {
|
||||
log.info("initialing sqlite connection.");
|
||||
connection = DriverManager.getConnection(SystemConstants.SQLITE_URL);
|
||||
|
||||
initialized = true;
|
||||
log.info("sqlite connection successfully initialized.");
|
||||
} catch (Exception e) {
|
||||
initialized = false;
|
||||
log.error("sql connection initialization exception: ", e);
|
||||
} finally {
|
||||
initLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否已经初始化
|
||||
*/
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
public static SQLiteConnector getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
system.cfg.log.onstart=true
|
||||
system.pool.core.size=4
|
||||
system.task.refresh.interval.ip=300
|
||||
system.ip.provider.type=IP_API
|
||||
system.http.overtime=3
|
||||
instance.aliyun.endpoint.url=alidns.cn-hangzhou.aliyuncs.com
|
||||
system.http.overtime=3
|
||||
@@ -2,10 +2,12 @@ package com.serliunx.ddns.test;
|
||||
|
||||
import com.serliunx.ddns.constant.InstanceType;
|
||||
import com.serliunx.ddns.constant.SystemConstants;
|
||||
import com.serliunx.ddns.core.factory.DatabaseInstanceFactory;
|
||||
import com.serliunx.ddns.core.factory.InstanceFactory;
|
||||
import com.serliunx.ddns.core.factory.ListableInstanceFactory;
|
||||
import com.serliunx.ddns.core.factory.YamlFileInstanceFactory;
|
||||
import com.serliunx.ddns.core.instance.Instance;
|
||||
import com.serliunx.ddns.support.sqlite.SQLiteConnector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -28,4 +30,10 @@ public class FactoryTest {
|
||||
System.out.println(k + ": " + v);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDatabaseFactory() {
|
||||
ListableInstanceFactory factory = new DatabaseInstanceFactory(SQLiteConnector.getInstance());
|
||||
factory.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.serliunx.ddns.test.support;
|
||||
|
||||
import com.serliunx.ddns.support.ipprovider.IpApiProvider;
|
||||
import com.serliunx.ddns.support.ipprovider.Provider;
|
||||
import com.serliunx.ddns.support.ipprovider.ScheduledProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 供应器测试
|
||||
*
|
||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||
* @version 1.0.3
|
||||
* @since 2024/11/25
|
||||
*/
|
||||
public class ProviderTest {
|
||||
|
||||
@Test
|
||||
public void testIpApiProvider() {
|
||||
Provider provider = new IpApiProvider();
|
||||
System.out.println(provider.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScheduledProvider() throws Exception {
|
||||
ScheduledProvider provider = new ScheduledProvider(new IpApiProvider(), 3);
|
||||
provider.changeTimePeriod(10);
|
||||
TimeUnit.SECONDS.sleep(60);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user