diff --git a/domain/pom.xml b/domain/pom.xml
new file mode 100755
index 0000000..f7442eb
--- /dev/null
+++ b/domain/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ com.xiang
+ xservice-scirpt
+ 1.0-SNAPSHOT
+
+
+ domain
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ com.xiang
+ facade
+ 1.0-SNAPSHOT
+
+
+
+ com.aliyun
+ alidns20150109
+ 3.4.7
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.3.0.RELEASE
+
+ exec
+
+ com.xiang.DomainApplication
+ ZIP
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/domain/src/main/java/com/xiang/DomainApplication.java b/domain/src/main/java/com/xiang/DomainApplication.java
new file mode 100755
index 0000000..b6351bc
--- /dev/null
+++ b/domain/src/main/java/com/xiang/DomainApplication.java
@@ -0,0 +1,17 @@
+package com.xiang;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-10 16:43
+ */
+@SpringBootApplication
+@EnableScheduling
+public class DomainApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DomainApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/domain/src/main/java/com/xiang/common/Result.java b/domain/src/main/java/com/xiang/common/Result.java
new file mode 100755
index 0000000..304b435
--- /dev/null
+++ b/domain/src/main/java/com/xiang/common/Result.java
@@ -0,0 +1,51 @@
+package com.xiang.common;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-05-09 14:09
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Result {
+
+ private String code;
+
+ private String message;
+
+ private List data;
+
+ public static Result success(String message) {
+ return new Result("200", message, null);
+ }
+
+
+ public static Result success(String message, List data) {
+ return new Result("200", message, data);
+ }
+ public static Result success(String message, T data) {
+ return new Result("200", message, Collections.singletonList(data));
+ }
+
+ public static Result error(String message) {
+ return new Result("500", message, null);
+ }
+
+ public static Result error(String message, T data) {
+ return new Result("500", message, Collections.singletonList(data));
+ }
+ public static Result error(String message, List data) {
+ return new Result("500", message, data);
+ }
+
+ public static Result error(String code, String message) {
+ return new Result(code, message, null);
+ }
+}
diff --git a/domain/src/main/java/com/xiang/controller/DynamicDomainController.java b/domain/src/main/java/com/xiang/controller/DynamicDomainController.java
new file mode 100755
index 0000000..323e939
--- /dev/null
+++ b/domain/src/main/java/com/xiang/controller/DynamicDomainController.java
@@ -0,0 +1,54 @@
+package com.xiang.controller;
+
+import com.xiang.common.Result;
+import com.xiang.service.DomainService;
+import com.xiang.utils.IpUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+
+/**
+ * 域名动态解析
+ *
+ * @Author: xiang
+ * @Date: 2025-06-10 16:44
+ */
+@RestController
+@RequestMapping("/system/domain")
+@Slf4j
+@RequiredArgsConstructor
+public class DynamicDomainController {
+
+ private final DomainService domainService;
+
+ @GetMapping("/getIp")
+ public Result getPublicIp() {
+ String publicIp;
+ try {
+ publicIp = IpUtils.getPublicIp();
+ } catch (IOException e) {
+ log.error("获取公网IP失败, time:{}", LocalDateTime.now(), e);
+ return Result.error("获取公网IP失败");
+ }
+ return Result.success("获取公网IP成功", publicIp);
+ }
+
+ @PostMapping("/ddns")
+ public Result dynamicDomainAnalysis() {
+ try {
+ String publicIp = IpUtils.getPublicIp();
+ log.info("获取公网IP成功,time:{}, ip:{}", LocalDateTime.now(), publicIp);
+ domainService.dynamicDomainAnalysis(publicIp);
+ return Result.success("获取公网IP成功");
+ } catch (Exception e) {
+ log.error("获取公网IP失败, time:{}", LocalDateTime.now(), e);
+ return Result.error("获取公网IP失败");
+ }
+ }
+}
diff --git a/domain/src/main/java/com/xiang/entity/resp/PublicIpResp.java b/domain/src/main/java/com/xiang/entity/resp/PublicIpResp.java
new file mode 100755
index 0000000..0f36fa2
--- /dev/null
+++ b/domain/src/main/java/com/xiang/entity/resp/PublicIpResp.java
@@ -0,0 +1,22 @@
+package com.xiang.entity.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-11 15:55
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PublicIpResp {
+ private String code;
+
+ private String message;
+
+ private List data;
+}
diff --git a/domain/src/main/java/com/xiang/schedule/DynamicDomainSchedule.java b/domain/src/main/java/com/xiang/schedule/DynamicDomainSchedule.java
new file mode 100755
index 0000000..c706f62
--- /dev/null
+++ b/domain/src/main/java/com/xiang/schedule/DynamicDomainSchedule.java
@@ -0,0 +1,38 @@
+package com.xiang.schedule;
+
+import com.xiang.service.DomainServiceImpl;
+import com.xiang.utils.IpUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-10 17:21
+ */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class DynamicDomainSchedule {
+
+ private final DomainServiceImpl domainService;
+
+ @Scheduled(cron = "0 0/5 * * * ? ")
+ public void dynamicDomainSchedule() {
+ String publicIp = "";
+ try {
+ publicIp = IpUtils.getPublicIp();
+ } catch (Exception e) {
+ log.error("获取公网ip失败,", e);
+ }
+ if (StringUtils.isNotBlank(publicIp)) {
+ try {
+ domainService.dynamicDomainAnalysis(publicIp);
+ } catch (Exception e) {
+ log.error("动态解析公网ip失败, ip:{}", publicIp, e);
+ }
+ }
+ }
+}
diff --git a/domain/src/main/java/com/xiang/service/DomainService.java b/domain/src/main/java/com/xiang/service/DomainService.java
new file mode 100755
index 0000000..ec3eb90
--- /dev/null
+++ b/domain/src/main/java/com/xiang/service/DomainService.java
@@ -0,0 +1,14 @@
+package com.xiang.service;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-10 16:48
+ */
+public interface DomainService {
+
+ /**
+ * 动态域名解析
+ * @param publicIp 动态ip
+ */
+ void dynamicDomainAnalysis(String publicIp) throws Exception;
+}
diff --git a/domain/src/main/java/com/xiang/service/DomainServiceImpl.java b/domain/src/main/java/com/xiang/service/DomainServiceImpl.java
new file mode 100755
index 0000000..ddaa4c5
--- /dev/null
+++ b/domain/src/main/java/com/xiang/service/DomainServiceImpl.java
@@ -0,0 +1,101 @@
+package com.xiang.service;
+
+
+import com.aliyun.alidns20150109.Client;
+import com.aliyun.alidns20150109.models.AddDomainRecordRequest;
+import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsRequest;
+import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponse;
+import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponseBody;
+import com.aliyun.alidns20150109.models.UpdateDomainRecordRequest;
+import com.aliyun.teaopenapi.models.Config;
+import com.xiang.dingTalk.service.DingTalkService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-10 16:48
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class DomainServiceImpl implements DomainService {
+
+ private static final String ACCESS_KEY_ID = "LTAI5tDMjaVF8Bbqcpp4dmvP";
+ private static final String ACCESS_KEY_SECRET = "nkmnaNjWQy5984C5kjyS0oDmdMKGQd";
+ /**
+ * 根域名
+ */
+ private static final String DOMAIN_NAME = "xiangtech.xyz";
+ /**
+ * 主机记录,例如 home.example.com
+ */
+ @Value("${aliyun.dns.RR}")
+ private String rr;
+ private static final String TYPE = "A";
+
+ private final DingTalkService dingTalkService;
+ @Value("${DingTalk.chatId}")
+ private String chatId;
+
+ @Override
+ public void dynamicDomainAnalysis(String publicIp) throws Exception {
+ Client client = createClient();
+
+ // 查询记录
+ DescribeSubDomainRecordsRequest query = new DescribeSubDomainRecordsRequest()
+ .setSubDomain(rr + "." + DOMAIN_NAME)
+ .setType(TYPE);
+ DescribeSubDomainRecordsResponse response = client.describeSubDomainRecords(query);
+ List records =
+ response.getBody().getDomainRecords().getRecord();
+
+ if (records.isEmpty()) {
+ log.info("未找到记录,添加记录..., ip:{}", publicIp);
+ addDnsRecord(client, publicIp);
+ dingTalkService.sendChatMessage(chatId, "动态解析公网ip成功,域名:" + rr + "." + DOMAIN_NAME + ", 新ip:" + publicIp);
+ } else {
+ String recordId = records.get(0).getRecordId();
+ String currentValue = records.get(0).getValue();
+ if (!publicIp.equals(currentValue)) {
+ log.info("IP变更,更新记录...,ip:{}", publicIp);
+ updateDnsRecord(client, recordId, publicIp);
+ dingTalkService.sendChatMessage(chatId, "动态解析公网ip成功,域名:" + rr + "." + DOMAIN_NAME + ", 新ip:" + publicIp);
+ } else {
+ log.info("ip未变更,无需修改,ip:{}", publicIp);
+ }
+ }
+ }
+
+ private Client createClient() throws Exception {
+ Config config = new Config()
+ .setAccessKeyId(ACCESS_KEY_ID)
+ .setAccessKeySecret(ACCESS_KEY_SECRET)
+ .setEndpoint("alidns.cn-hangzhou.aliyuncs.com");
+ return new Client(config);
+ }
+
+ private void updateDnsRecord(Client client, String recordId, String newIp) throws Exception {
+ UpdateDomainRecordRequest request = new UpdateDomainRecordRequest()
+ .setRecordId(recordId)
+ .setRR(rr)
+ .setType(TYPE)
+ .setValue(newIp);
+ client.updateDomainRecord(request);
+ log.info("更新成功: ,newIP:{}", newIp);
+ }
+
+ private void addDnsRecord(Client client, String ip) throws Exception {
+ AddDomainRecordRequest request = new AddDomainRecordRequest()
+ .setDomainName(DOMAIN_NAME)
+ .setRR(rr)
+ .setType(TYPE)
+ .setValue(ip);
+ client.addDomainRecord(request);
+ log.info("添加成功: ip:{}", ip);
+ }
+}
diff --git a/domain/src/main/java/com/xiang/utils/HttpUtils.java b/domain/src/main/java/com/xiang/utils/HttpUtils.java
new file mode 100755
index 0000000..3023740
--- /dev/null
+++ b/domain/src/main/java/com/xiang/utils/HttpUtils.java
@@ -0,0 +1,121 @@
+package com.xiang.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-05-08 14:39
+ */
+@Slf4j
+public class HttpUtils {
+
+ private final static int socketTimeOut = 60 * 1000;
+ private final static int connectTimeout = 60 * 1000;
+ private final static int connectionRequestTimeout = 15 * 1000;
+ private final static int defaultMaxPerRoute = 500;
+ private final static int maxTotal = 2000;
+
+ public static String doPost(String url, Map header, String jsonParams) {
+ RequestConfig requestConfig = RequestConfig.custom()
+ // 设置连接超时时间
+ .setConnectTimeout(connectTimeout)
+ // 设置Socket超时时间
+ .setSocketTimeout(socketTimeOut)
+ .setConnectionRequestTimeout(connectionRequestTimeout)
+ .build();
+ //创建httpClient对象
+ CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
+ CloseableHttpResponse response = null;
+ String result = "";
+ try {
+ // 创建http请求
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.addHeader("Content-Type", "application/json");
+ // 创建请求内容
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ // 设置请求头
+ if (null != header && !header.isEmpty()) {
+ Set> entries = header.entrySet();
+ for (Map.Entry e : entries) {
+ httpPost.setHeader(e.getKey(), e.getValue());
+ }
+ }
+ response = httpClient.execute(httpPost);
+ result = EntityUtils.toString(response.getEntity(), "utf-8");
+ } catch (Exception e) {
+ log.error("doPost异常", e);
+ } finally {
+ //关闭资源
+ closeResource(response, httpClient);
+ }
+ return result;
+ }
+
+ public static String doGet(String url, Map header, Map param) {
+ RequestConfig requestConfig = RequestConfig.custom()
+ // 设置连接超时时间
+ .setConnectTimeout(connectTimeout)
+ // 设置Socket超时时间
+ .setSocketTimeout(socketTimeOut)
+ .setConnectionRequestTimeout(connectionRequestTimeout)
+ .build();
+ CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
+ CloseableHttpResponse response;
+ String result = "";
+ try {
+ String request = "";
+ if (MapUtils.isNotEmpty(param)) {
+ StringBuilder req = new StringBuilder("?");
+ for (Map.Entry entry : param.entrySet()) {
+ req.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+ }
+ request = req.substring(0, req.length() - 1);
+ }
+
+ HttpGet httpGet = new HttpGet(url + request);
+ httpGet.addHeader("Content-Type", "application/json");
+ if (MapUtils.isNotEmpty(header)) {
+ for (Map.Entry entry : header.entrySet()) {
+ httpGet.setHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ log.info("doGet请求:请求地址:{}", url + request);
+ response = httpClient.execute(httpGet);
+ result = EntityUtils.toString(response.getEntity(), "utf-8");
+ } catch (Exception e) {
+ log.error("doGet异常:", e);
+ }
+ return result;
+ }
+
+ /**
+ * @Description 关闭资源
+ */
+ private static void closeResource(Closeable... resources) {
+ try {
+ for (Closeable resource : resources) {
+ if (resource != null) {
+ resource.close();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/domain/src/main/java/com/xiang/utils/IpUtils.java b/domain/src/main/java/com/xiang/utils/IpUtils.java
new file mode 100755
index 0000000..d5febc5
--- /dev/null
+++ b/domain/src/main/java/com/xiang/utils/IpUtils.java
@@ -0,0 +1,22 @@
+package com.xiang.utils;
+
+import com.google.common.collect.Maps;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @Author: xiang
+ * @Date: 2025-06-10 16:50
+ */
+public class IpUtils {
+
+ private final static String PUBLIC_IP_URL = "https://api-ipv4.ip.sb/ip";
+
+ public static String getPublicIp() throws IOException {
+
+ Map header = Maps.newHashMap();
+ header.put("User-Agent", "Mozilla/5.0");
+ return HttpUtils.doGet(PUBLIC_IP_URL, header, null).trim();
+ }
+}
diff --git a/domain/src/main/resources/application-local.yml b/domain/src/main/resources/application-local.yml
new file mode 100755
index 0000000..e2ad775
--- /dev/null
+++ b/domain/src/main/resources/application-local.yml
@@ -0,0 +1,10 @@
+spring:
+ datasource:
+ url: jdbc:mysql:///xservice-script?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
+ username: root
+ password: 123456
+ driver-class-name: com.mysql.cj.jdbc.Driver
+
+aliyun:
+ dns:
+ RR: test21
\ No newline at end of file
diff --git a/domain/src/main/resources/application-nas.yml b/domain/src/main/resources/application-nas.yml
new file mode 100755
index 0000000..23b4044
--- /dev/null
+++ b/domain/src/main/resources/application-nas.yml
@@ -0,0 +1,10 @@
+spring:
+ datasource:
+ url: jdbc:mysql://172.28.159.213:3306/xservice-script?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
+ username: root
+ password: 123456
+ driver-class-name: com.mysql.cj.jdbc.Driver
+
+aliyun:
+ dns:
+ RR: client
\ No newline at end of file
diff --git a/domain/src/main/resources/application-prod.yml b/domain/src/main/resources/application-prod.yml
new file mode 100755
index 0000000..7a478f3
--- /dev/null
+++ b/domain/src/main/resources/application-prod.yml
@@ -0,0 +1,10 @@
+spring:
+ datasource:
+ url: jdbc:mysql://172.28.159.213:3306/xservice-script?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
+ username: root
+ password: 123456
+ driver-class-name: com.mysql.cj.jdbc.Driver
+
+aliyun:
+ dns:
+ RR: general
\ No newline at end of file
diff --git a/domain/src/main/resources/application.yml b/domain/src/main/resources/application.yml
new file mode 100755
index 0000000..8732c39
--- /dev/null
+++ b/domain/src/main/resources/application.yml
@@ -0,0 +1,18 @@
+mybatis:
+ mapper-locations:
+ - classpath*:mapper/*.xml
+ configuration:
+ map-underscore-to-camel-case: true
+
+DingTalk:
+ # 钉钉消息用户,用逗号隔开
+ userList: "450841600726084717"
+ # 钉钉消息群ID,需要调用/chat/create api创建群返回
+ chatId: "chatd16d8daeea33b36b73588c676d508096"
+
+server:
+ port: 8080
+
+spring:
+ profiles:
+ active: local
\ No newline at end of file
diff --git a/domain/src/main/resources/logback-spring.xml b/domain/src/main/resources/logback-spring.xml
new file mode 100755
index 0000000..d222df7
--- /dev/null
+++ b/domain/src/main/resources/logback-spring.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+ ${APP_NAME}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %boldGreen(%contextName): %boldCyan(%d{yyyy-MM-dd HH:mm:ss:SSS}) %highlight([%c]) %boldMagenta([%t]) %boldCyan([%L]) %highlight([traceId:%X{traceId:-},spanId:%X{spanId:-},localIp:%X{localIp:-}]) %boldGreen([%p]) - %msg%n
+
+
+ UTF-8
+
+
+
+
+
+
+
+ ${LOG_HOME}/debug-%d{yyyy-MM-dd}.log
+
+ ${LOG_MAX_HISTORY}
+
+
+
+ %contextName: %d{yyyy-MM-dd HH:mm:ss.SSS} [%c][%t][%L][%p] [traceId:%X{traceId:-},spanId:%X{spanId:-},localIp:%X{localIp:-}] - %msg%n
+ UTF-8
+
+
+
+ debug
+ ACCEPT
+ DENY
+
+
+
+
+
+
+
+ ${LOG_HOME}/info-%d{yyyy-MM-dd}.log
+
+ ${LOG_MAX_HISTORY}
+
+
+
+ %contextName: %d{yyyy-MM-dd HH:mm:ss.SSS} [%c][%t][%L][%p] [traceId:%X{traceId:-},spanId:%X{spanId:-},localIp:%X{localIp:-}] - %msg%n
+ UTF-8
+
+
+
+
+ info
+ ACCEPT
+ DENY
+
+
+
+
+
+
+
+ ${LOG_HOME}/error-%d{yyyy-MM-dd}.log
+
+ ${LOG_MAX_HISTORY}
+
+
+
+ %contextName: %d{yyyy-MM-dd HH:mm:ss.SSS} [%c][%t][%L][%p] [traceId:%X{traceId:-},spanId:%X{spanId:-},localIp:%X{localIp:-}] - %msg%n
+ UTF-8
+
+
+
+ error
+ ACCEPT
+ DENY
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/script/src/main/java/com/xiang/schedule/xb/FundInfoQueryJob.java b/script/src/main/java/com/xiang/schedule/xb/FundInfoQueryJob.java
index d80843d..844adf1 100644
--- a/script/src/main/java/com/xiang/schedule/xb/FundInfoQueryJob.java
+++ b/script/src/main/java/com/xiang/schedule/xb/FundInfoQueryJob.java
@@ -244,6 +244,7 @@ public class FundInfoQueryJob {
if (Objects.equals(type, 1)) {
code = Arrays.stream(codeArr.split(", ")).collect(Collectors.toList());
}
+ return Lists.newArrayList();
} else {
code = lists.stream().map(XbFundList::getCode).collect(Collectors.toList());
}