diff --git a/pom.xml b/pom.xml index 42c36ac..2d2604e 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,6 @@ 1.2.12 2.17.0 1.30 - 13.2.1 3.0.14 3.1.1002 @@ -53,23 +52,6 @@ tencentcloud-sdk-java-dnspod ${tencent.dnspod.sdk.version} - - - io.github.openfeign - feign-core - ${feign.core.version} - - - io.github.openfeign - feign-slf4j - ${feign.core.version} - - - org.slf4j - slf4j-api - - - junit junit diff --git a/src/main/java/com/serliunx/ddns/ManagerLite.java b/src/main/java/com/serliunx/ddns/ManagerLite.java index 2067833..6131a37 100644 --- a/src/main/java/com/serliunx/ddns/ManagerLite.java +++ b/src/main/java/com/serliunx/ddns/ManagerLite.java @@ -1,9 +1,12 @@ package com.serliunx.ddns; +import com.serliunx.ddns.config.Configuration; import com.serliunx.ddns.config.PropertiesConfiguration; import com.serliunx.ddns.constant.SystemConstants; import com.serliunx.ddns.core.context.FileInstanceContext; +import com.serliunx.ddns.core.context.MultipleSourceInstanceContext; import com.serliunx.ddns.support.SystemInitializer; +import com.serliunx.ddns.support.okhttp.HttpClient; /** * 启动类 @@ -14,17 +17,65 @@ import com.serliunx.ddns.support.SystemInitializer; */ public final class ManagerLite { + /** + * 配置信息 + */ + private static Configuration configuration; + /** + * 实例容器 + */ + private static MultipleSourceInstanceContext instanceContext; + /** + * 系统初始化器 + */ + private static SystemInitializer systemInitializer; + public static void main(String[] args) { - // 容器初始化 - init(); + + // 配置初始化 + initConfiguration(); + + // 相关工具初始化 + initTools(); + + // 初始化实例容器 + initContext(); + + // 系统初始化 + initSystem(); } - private static void init() { - SystemInitializer systemInitializer = SystemInitializer + /** + * 初始化实例容器 + */ + private static void initContext() { + instanceContext = new FileInstanceContext(); + } + + /** + * 配置初始化 + */ + private static void initConfiguration() { + configuration = new PropertiesConfiguration(SystemConstants.USER_SETTINGS_PROPERTIES_PATH); + } + + /** + * 相关工具初始化 + */ + private static void initTools() { + // http 工具类初始化 + HttpClient.init(configuration); + } + + /** + * 系统初始化 + */ + private static void initSystem() { + systemInitializer = SystemInitializer .configurer() .clearCache(false) - .configuration(new PropertiesConfiguration(SystemConstants.USER_SETTINGS_PROPERTIES_PATH)) - .instanceContext(new FileInstanceContext()) + .configuration(configuration) + .instanceContext(instanceContext) .done(); systemInitializer.refresh(); } diff --git a/src/main/java/com/serliunx/ddns/client/IPAddressClient.java b/src/main/java/com/serliunx/ddns/client/IPAddressClient.java deleted file mode 100644 index 92a7a02..0000000 --- a/src/main/java/com/serliunx/ddns/client/IPAddressClient.java +++ /dev/null @@ -1,42 +0,0 @@ -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 feign.Feign; -import feign.Logger; -import feign.RequestLine; -import feign.Retryer; -import feign.slf4j.Slf4jLogger; - -/** - * 本机外网IP地址获取 - * - * @author SerLiunx - * @version 1.0.0 - * @since 2024/5/15 - */ -@SuppressWarnings("all") -public interface IPAddressClient { - - static final String url = "http://ip-api.com"; - - static final IPAddressClient instance = getInstance(); - - /** - * 获取本机外网IP地址 - * @return IPAddressResponse - */ - @RequestLine("GET /json") - IPAddressResponse getIPAddress(); - - static IPAddressClient getInstance() { - return Feign.builder() - .logger(new Slf4jLogger()) - .logLevel(Logger.Level.BASIC) - .retryer(Retryer.NEVER_RETRY) - .encoder(JacksonEncoder.getInstance()) - .decoder(JacksonDecoder.getInstance()) - .target(IPAddressClient.class, url); - } -} diff --git a/src/main/java/com/serliunx/ddns/config/ConfigurationKeys.java b/src/main/java/com/serliunx/ddns/config/ConfigurationKeys.java index 8722eab..a9171d2 100644 --- a/src/main/java/com/serliunx/ddns/config/ConfigurationKeys.java +++ b/src/main/java/com/serliunx/ddns/config/ConfigurationKeys.java @@ -30,4 +30,9 @@ public final class ConfigurationKeys { * 阿里云解析线路 */ public static final String KEY_ALIYUN_ENDPOINT = "instance.aliyun.endpoint.url"; + + /** + * http请求超时时间(秒) + */ + public static final String KEY_HTTP_OVERTIME = "system.http.overtime"; } diff --git a/src/main/java/com/serliunx/ddns/core/factory/InstanceFactory.java b/src/main/java/com/serliunx/ddns/core/factory/InstanceFactory.java index 699eda1..1cf3222 100644 --- a/src/main/java/com/serliunx/ddns/core/factory/InstanceFactory.java +++ b/src/main/java/com/serliunx/ddns/core/factory/InstanceFactory.java @@ -18,12 +18,14 @@ public interface InstanceFactory extends Priority, Comparable, /** * 添加实例 *
  • 此方法默认为不覆盖的方式添加, 即如果存在则添加失败, 没有任何返回值和异常. + * * @param instance 实例信息 */ void addInstance(Instance instance); /** * 根据实例名称获取实例 + * * @param instanceName 实例名称 * @return 实例信息, 如果不存在则会抛出异常 */ @@ -31,7 +33,7 @@ public interface InstanceFactory extends Priority, Comparable, @Override default int compareTo(InstanceFactory o) { - if(getPriority() < o.getPriority()){ + if (getPriority() < o.getPriority()) { return 1; } else if (this.getPriority() > o.getPriority()) { return -1; diff --git a/src/main/java/com/serliunx/ddns/support/ConfigurationContextHolder.java b/src/main/java/com/serliunx/ddns/support/ConfigurationContextHolder.java index dc5238c..365d7ff 100644 --- a/src/main/java/com/serliunx/ddns/support/ConfigurationContextHolder.java +++ b/src/main/java/com/serliunx/ddns/support/ConfigurationContextHolder.java @@ -12,7 +12,7 @@ import com.serliunx.ddns.config.Configuration; */ public final class ConfigurationContextHolder { - private static final ThreadLocal CONFIGURATION_HOLDER = new ThreadLocal<>(); + private static volatile Configuration configuration; private ConfigurationContextHolder() {throw new UnsupportedOperationException();} @@ -22,7 +22,7 @@ public final class ConfigurationContextHolder { * @return 配置信息 */ public static Configuration getConfiguration() { - return CONFIGURATION_HOLDER.get(); + return configuration; } /** @@ -31,7 +31,10 @@ public final class ConfigurationContextHolder { * * @param configuration 配置信息 */ - public static void setConfiguration(Configuration configuration) { - CONFIGURATION_HOLDER.set(configuration); + public static synchronized void setConfiguration(Configuration configuration) { + if (ConfigurationContextHolder.configuration != null) { + return; + } + ConfigurationContextHolder.configuration = configuration; } } diff --git a/src/main/java/com/serliunx/ddns/support/SystemInitializer.java b/src/main/java/com/serliunx/ddns/support/SystemInitializer.java index 19cc1a8..011bd4d 100644 --- a/src/main/java/com/serliunx/ddns/support/SystemInitializer.java +++ b/src/main/java/com/serliunx/ddns/support/SystemInitializer.java @@ -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.client.IPAddressClient; -import com.serliunx.ddns.client.entity.IPAddressResponse; +import com.serliunx.ddns.support.okhttp.IPAddressResponse; +import com.serliunx.ddns.support.okhttp.HttpClient; import com.serliunx.ddns.thread.TaskThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -169,7 +169,7 @@ public final class SystemInitializer implements Refreshable, Clearable { scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> { InstanceContextHolder.setAdditional("ip-update"); log.info("正在尝试获取本机最新的IP地址."); - IPAddressResponse response = IPAddressClient.instance.getIPAddress(); + IPAddressResponse response = HttpClient.getIPAddress(); String ip; if(response != null && (ip = response.getQuery()) != null) { diff --git a/src/main/java/com/serliunx/ddns/support/feign/JacksonDecoder.java b/src/main/java/com/serliunx/ddns/support/feign/JacksonDecoder.java deleted file mode 100644 index 4a15f7e..0000000 --- a/src/main/java/com/serliunx/ddns/support/feign/JacksonDecoder.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.serliunx.ddns.support.feign; - -import com.fasterxml.jackson.databind.*; -import feign.FeignException; -import feign.Response; -import feign.Util; -import feign.codec.Decoder; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.lang.reflect.Type; -import java.util.Collections; - -/** - * feign解码器 - * - * @author SerLiunx - * @version 1.0.0 - * @since 2024/5/15 - */ -public class JacksonDecoder implements Decoder { - - private final ObjectMapper mapper; - private static final JacksonDecoder decoder = new JacksonDecoder(); - - private JacksonDecoder() { - this(Collections.emptyList()); - } - - private JacksonDecoder(Iterable modules) { - this(new ObjectMapper() - //设置下划线自动转化为驼峰命名 - .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModules(modules)); - } - - private JacksonDecoder(ObjectMapper mapper) { - this.mapper = mapper; - } - - public static Decoder getInstance() { - return decoder; - } - - @Override - public Object decode(Response response, Type type) throws FeignException, IOException { - if (response.status() == 404 || response.status() == 204) - return Util.emptyValueOf(type); - if (response.body() == null) - return null; - Reader reader = response.body().asReader(response.charset()); - if (!reader.markSupported()) { - reader = new BufferedReader(reader, 1); - } - //处理响应体字符流 - try{ - reader.mark(1); - if (reader.read() == -1) { - return null; - } - reader.reset(); - return mapper.readValue(reader, mapper.constructType(type)); - } catch (RuntimeJsonMappingException e) { - if (e.getCause() != null && e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } - throw e; - }finally { - response.close(); - } - } -} diff --git a/src/main/java/com/serliunx/ddns/support/feign/JacksonEncoder.java b/src/main/java/com/serliunx/ddns/support/feign/JacksonEncoder.java deleted file mode 100644 index 6f4a691..0000000 --- a/src/main/java/com/serliunx/ddns/support/feign/JacksonEncoder.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.serliunx.ddns.support.feign; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import feign.RequestTemplate; -import feign.Util; -import feign.codec.EncodeException; -import feign.codec.Encoder; - -import java.lang.reflect.Type; -import java.util.Collections; - -/** - * Feign兼容Jackson(反序列化返回值) - * - * @author SerLiunx - * @version 1.0.0 - * @since 2024/5/15 - */ -public class JacksonEncoder implements Encoder { - - private final ObjectMapper mapper; - private static final JacksonEncoder encoder = new JacksonEncoder(); - - private JacksonEncoder() { - this(Collections.emptyList()); - } - - private JacksonEncoder(Iterable modules) { - this(new ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_NULL) - .configure(SerializationFeature.INDENT_OUTPUT, true) - .registerModules(modules)); - } - - private JacksonEncoder(ObjectMapper mapper) { - this.mapper = mapper; - } - - public static Encoder getInstance() { - return encoder; - } - - @Override - public void encode(Object object, Type bodyType, RequestTemplate template) { - try { - JavaType javaType = mapper.getTypeFactory().constructType(bodyType); - template.body(mapper.writerFor(javaType).writeValueAsBytes(object), Util.UTF_8); - } catch (JsonProcessingException e) { - throw new EncodeException(e.getMessage(), 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 new file mode 100644 index 0000000..aa92f91 --- /dev/null +++ b/src/main/java/com/serliunx/ddns/support/okhttp/HttpClient.java @@ -0,0 +1,74 @@ +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +/** + * Http 客户端工具类 + *
  • 使用okhttp实现 + * + * @author SerLiunx + * @version 1.0.2 + * @since 2024/11/6 + */ +public final class HttpClient { + + private static OkHttpClient CLIENT = null; + + private static final Logger log = LoggerFactory.getLogger(HttpClient.class); + private static final ObjectMapper JSON_MAPPER = new JsonMapper(); + + private HttpClient() {throw new UnsupportedOperationException();} + + /** + * 获取本机的ip地址 + * + * @return 响应结果 + */ + public static IPAddressResponse getIPAddress() { + Request request = new Request.Builder() + .url("http://ip-api.com/json") + .get() + .build(); + + try (Response response = CLIENT.newCall(request).execute()) { + if (!response.isSuccessful() || response.body() == null) { + return null; + } + + String body = response.body().string(); + if (body.isEmpty()) { + return null; + } + + return JSON_MAPPER.readValue(body, IPAddressResponse.class); + } catch (Exception e) { + log.error("ip地址获取异常:", e); + } + return null; + } + + /** + * 初始化 + * + * @param configuration 配置信息 + */ + public static void init(Configuration configuration) { + Integer overtime = configuration.getInteger(ConfigurationKeys.KEY_HTTP_OVERTIME, 3); + + CLIENT = new OkHttpClient.Builder() + .connectTimeout(overtime, TimeUnit.SECONDS) + .readTimeout(overtime, TimeUnit.SECONDS) + .writeTimeout(overtime, TimeUnit.SECONDS) + .build(); + } +} diff --git a/src/main/java/com/serliunx/ddns/client/entity/IPAddressResponse.java b/src/main/java/com/serliunx/ddns/support/okhttp/IPAddressResponse.java similarity index 98% rename from src/main/java/com/serliunx/ddns/client/entity/IPAddressResponse.java rename to src/main/java/com/serliunx/ddns/support/okhttp/IPAddressResponse.java index 1eeda1f..b157c16 100644 --- a/src/main/java/com/serliunx/ddns/client/entity/IPAddressResponse.java +++ b/src/main/java/com/serliunx/ddns/support/okhttp/IPAddressResponse.java @@ -1,4 +1,4 @@ -package com.serliunx.ddns.client.entity; +package com.serliunx.ddns.support.okhttp; /** * IP地址查询响应 diff --git a/src/main/resources/settings.properties b/src/main/resources/settings.properties index 55a27e9..201698c 100644 --- a/src/main/resources/settings.properties +++ b/src/main/resources/settings.properties @@ -1,4 +1,5 @@ system.cfg.log.onstart=true system.pool.core.size=4 system.task.refresh.interval.ip=300 -instance.aliyun.endpoint.url=alidns.cn-hangzhou.aliyuncs.com \ No newline at end of file +instance.aliyun.endpoint.url=alidns.cn-hangzhou.aliyuncs.com +system.http.overtime=3 \ No newline at end of file diff --git a/src/test/java/com/serliunx/ddns/test/ContextTest.java b/src/test/java/com/serliunx/ddns/test/ContextTest.java index 01ba4d9..850993c 100644 --- a/src/test/java/com/serliunx/ddns/test/ContextTest.java +++ b/src/test/java/com/serliunx/ddns/test/ContextTest.java @@ -22,9 +22,9 @@ public class ContextTest { public void testGenericContext() { GenericInstanceContext genericInstanceContext = new GenericInstanceContext(true); -// genericInstanceContext.addListableInstanceFactory(new XmlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); -// genericInstanceContext.addListableInstanceFactory(new YamlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); -// genericInstanceContext.addListableInstanceFactory(new JsonFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); + genericInstanceContext.addListableInstanceFactory(new XmlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); + genericInstanceContext.addListableInstanceFactory(new YamlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); + genericInstanceContext.addListableInstanceFactory(new JsonFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR)); genericInstanceContext.refresh(); genericInstanceContext.getInstances().forEach(System.out::println); diff --git a/src/test/java/com/serliunx/ddns/test/support/ClientTest.java b/src/test/java/com/serliunx/ddns/test/support/ClientTest.java index e4dd4b1..930d87a 100644 --- a/src/test/java/com/serliunx/ddns/test/support/ClientTest.java +++ b/src/test/java/com/serliunx/ddns/test/support/ClientTest.java @@ -1,6 +1,5 @@ package com.serliunx.ddns.test.support; -import com.serliunx.ddns.client.IPAddressClient; import org.junit.Test; /** @@ -11,7 +10,6 @@ public class ClientTest { @Test public void test() { - IPAddressClient client = IPAddressClient.instance; - System.out.println(client.getIPAddress().getQuery()); + } }