diff --git a/src/main/java/com/serliunx/ddns/support/ipprovider/IcanhazipProvider.java b/src/main/java/com/serliunx/ddns/support/ipprovider/IcanhazipProvider.java new file mode 100644 index 0000000..2aba752 --- /dev/null +++ b/src/main/java/com/serliunx/ddns/support/ipprovider/IcanhazipProvider.java @@ -0,0 +1,17 @@ +package com.serliunx.ddns.support.ipprovider; + +import com.serliunx.ddns.support.okhttp.HttpClient; + +/** + * ip数据提供商 icanhazip + * + * @author SerLiunx + * @since 2024/12/6 + */ +public final class IcanhazipProvider extends AbstractProvider { + + @Override + protected String doGet() { + return HttpClient.httpGet("https://icanhazip.com/"); + } +} diff --git a/src/main/java/com/serliunx/ddns/support/ipprovider/IpApiProvider.java b/src/main/java/com/serliunx/ddns/support/ipprovider/IpApiProvider.java index 5d7e20b..e0cedf5 100644 --- a/src/main/java/com/serliunx/ddns/support/ipprovider/IpApiProvider.java +++ b/src/main/java/com/serliunx/ddns/support/ipprovider/IpApiProvider.java @@ -1,5 +1,8 @@ package com.serliunx.ddns.support.ipprovider; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.serliunx.ddns.support.okhttp.HttpClient; import com.serliunx.ddns.support.okhttp.IPAddressResponse; @@ -13,12 +16,22 @@ import com.serliunx.ddns.support.okhttp.IPAddressResponse; */ public final class IpApiProvider extends AbstractProvider { + private static final ObjectMapper JSON_MAPPER = new JsonMapper(); + @Override protected String doGet() { - IPAddressResponse response = HttpClient.getIPAddress(); - if (response == null) { + final String response = HttpClient.httpGet("http://ip-api.com/json"); + if (response == null + || response.isEmpty()) { return null; } - return response.getQuery(); + + try { + IPAddressResponse ipAddressResponse = JSON_MAPPER.readValue(response, IPAddressResponse.class); + + return ipAddressResponse.getQuery(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/com/serliunx/ddns/support/okhttp/HttpClient.java b/src/main/java/com/serliunx/ddns/support/okhttp/HttpClient.java index 130a961..787a12b 100644 --- a/src/main/java/com/serliunx/ddns/support/okhttp/HttpClient.java +++ b/src/main/java/com/serliunx/ddns/support/okhttp/HttpClient.java @@ -1,12 +1,11 @@ package com.serliunx.ddns.support.okhttp; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; import com.serliunx.ddns.config.Configuration; import com.serliunx.ddns.config.ConfigurationKeys; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import okhttp3.ResponseBody; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,10 +21,9 @@ import java.util.concurrent.TimeUnit; */ public final class HttpClient { - private static OkHttpClient CLIENT = null; + private static OkHttpClient CLIENT; 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();} @@ -39,29 +37,28 @@ public final class HttpClient { } /** - * 获取本机的ip地址 + * 发送GET请求 * - * @return 响应结果 + * @param url 请求地址 + * @return 响应 */ - public static IPAddressResponse getIPAddress() { - Request request = new Request.Builder() - .url("http://ip-api.com/json") + public static String httpGet(String url) { + final Request request = new Request.Builder() + .url(url) .get() .build(); try (Response response = CLIENT.newCall(request).execute()) { - if (!response.isSuccessful() || response.body() == null) { + if (!response.isSuccessful() + || response.body() == null) { return null; } - String body = response.body().string(); - if (body.isEmpty()) { - return null; - } + final ResponseBody responseBody = response.body(); - return JSON_MAPPER.readValue(body, IPAddressResponse.class); + return responseBody.string(); } catch (Exception e) { - log.error("ip地址获取异常:", e); + log.error("http 接口异常:", e); } return null; } diff --git a/src/main/java/com/serliunx/ddns/support/sqlite/SQLiteConnector.java b/src/main/java/com/serliunx/ddns/support/sqlite/SQLiteConnector.java index ce79f19..2df1e67 100644 --- a/src/main/java/com/serliunx/ddns/support/sqlite/SQLiteConnector.java +++ b/src/main/java/com/serliunx/ddns/support/sqlite/SQLiteConnector.java @@ -20,11 +20,10 @@ import java.util.concurrent.locks.ReentrantLock; public final class SQLiteConnector implements Refreshable { private volatile Connection connection; + private volatile boolean initialized = false; 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(); @@ -53,6 +52,9 @@ public final class SQLiteConnector implements Refreshable { log.info("initialing sqlite connection."); connection = DriverManager.getConnection(SystemConstants.SQLITE_URL); + // 尝试创建数据库表, 只会执行一次 + tryCreateTables(); + initialized = true; log.info("sqlite connection successfully initialized."); } catch (Exception e) { @@ -63,6 +65,16 @@ public final class SQLiteConnector implements Refreshable { } } + /** + * 尝试创建数据库表 + *
  • 不存在时创建 + */ + private void tryCreateTables() { + if (connection == null) { + throw new IllegalStateException("sql connection not initialized"); + } + } + /** * 是否已经初始化 */ diff --git a/src/main/java/com/serliunx/ddns/support/thread/ThreadFactoryBuilder.java b/src/main/java/com/serliunx/ddns/support/thread/ThreadFactoryBuilder.java index 8e7164b..33e472d 100644 --- a/src/main/java/com/serliunx/ddns/support/thread/ThreadFactoryBuilder.java +++ b/src/main/java/com/serliunx/ddns/support/thread/ThreadFactoryBuilder.java @@ -35,14 +35,25 @@ public final class ThreadFactoryBuilder { * @return 线程工厂 */ public ThreadFactory ofNamePattern(final String pattern) { - return new ThreadFactory() { + return new NamePatternThreadFactory(pattern); + } - private final AtomicInteger counter = new AtomicInteger(0); + /** + * 线程工厂之模板名称 + */ + private static class NamePatternThreadFactory implements ThreadFactory { - @Override - public Thread newThread(@NotNull Runnable r) { - return new Thread(r, String.format(pattern, counter.getAndIncrement())); - } - }; + private final AtomicInteger counter = new AtomicInteger(0); + + private final String pattern; + + public NamePatternThreadFactory(String pattern) { + this.pattern = pattern; + } + + @Override + public Thread newThread(@NotNull Runnable r) { + return new Thread(r, String.format(pattern, counter.getAndIncrement())); + } } } diff --git a/src/test/java/com/serliunx/ddns/test/ContextTest.java b/src/test/java/com/serliunx/ddns/test/ContextTest.java index 850993c..35862f5 100644 --- a/src/test/java/com/serliunx/ddns/test/ContextTest.java +++ b/src/test/java/com/serliunx/ddns/test/ContextTest.java @@ -5,11 +5,10 @@ import com.serliunx.ddns.constant.SystemConstants; import com.serliunx.ddns.core.context.FileInstanceContext; import com.serliunx.ddns.core.context.GenericInstanceContext; import com.serliunx.ddns.core.context.MultipleSourceInstanceContext; -import com.serliunx.ddns.core.factory.JsonFileInstanceFactory; -import com.serliunx.ddns.core.factory.XmlFileInstanceFactory; -import com.serliunx.ddns.core.factory.YamlFileInstanceFactory; +import com.serliunx.ddns.core.factory.*; import com.serliunx.ddns.core.instance.AliyunInstance; import com.serliunx.ddns.core.instance.Instance; +import com.serliunx.ddns.support.sqlite.SQLiteConnector; import org.junit.Test; /** @@ -33,13 +32,13 @@ public class ContextTest { } @Test - public void testFileContext(){ + public void testFileContext() { FileInstanceContext context = new FileInstanceContext(); context.getSortedListableInstanceFactories().forEach(System.out::println); } @Test - public void testEmptyContext(){ + public void testEmptyContext() { GenericInstanceContext instanceContext = new GenericInstanceContext(false); instanceContext.addListableInstanceFactory(new YamlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); @@ -52,4 +51,14 @@ public class ContextTest { instanceContext.getInstances().forEach(System.out::println); } + + @Test + public void testGic1() { + MultipleSourceInstanceContext context = new GenericInstanceContext(true); + ListableInstanceFactory factory = new DatabaseInstanceFactory(SQLiteConnector.getInstance()); + + context.addListableInstanceFactory(factory); + + context.refresh(); + } } diff --git a/src/test/java/com/serliunx/ddns/test/support/ProviderTest.java b/src/test/java/com/serliunx/ddns/test/support/ProviderTest.java index 9fdef6f..e7429ac 100644 --- a/src/test/java/com/serliunx/ddns/test/support/ProviderTest.java +++ b/src/test/java/com/serliunx/ddns/test/support/ProviderTest.java @@ -1,5 +1,6 @@ package com.serliunx.ddns.test.support; +import com.serliunx.ddns.support.ipprovider.IcanhazipProvider; import com.serliunx.ddns.support.ipprovider.IpApiProvider; import com.serliunx.ddns.support.ipprovider.Provider; import com.serliunx.ddns.support.ipprovider.ScheduledProvider; @@ -26,4 +27,10 @@ public class ProviderTest { String ip = provider.get(); System.out.println(ip); } + + @Test + public void testIcanhazipProvider() { + Provider provider = new IcanhazipProvider(); + System.out.println(provider.get()); + } }