diff --git a/pom.xml b/pom.xml
index d1ec1b3..f30f2f6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,10 +125,11 @@
org.springframework.boot
spring-boot-starter-web
-
- org.springframework.boot
- spring-boot-starter-actuator
-
+
+
+
+
+
commons-io
commons-io
@@ -174,6 +175,13 @@
com.fasterxml.jackson.core
jackson-databind
+
+
+
+ com.jcraft
+ jsch
+ 0.1.55
+
diff --git a/xservice-common/pom.xml b/xservice-common/pom.xml
index 51b7a8a..b4676bd 100644
--- a/xservice-common/pom.xml
+++ b/xservice-common/pom.xml
@@ -8,7 +8,7 @@
xservice-basic
1.1
- 1.2
+ 1.3
xservice-common
diff --git a/xservice-common/src/main/java/com/xiang/xservice/basic/utils/SSHManager.java b/xservice-common/src/main/java/com/xiang/xservice/basic/utils/SSHManager.java
new file mode 100644
index 0000000..b1bac91
--- /dev/null
+++ b/xservice-common/src/main/java/com/xiang/xservice/basic/utils/SSHManager.java
@@ -0,0 +1,39 @@
+package com.xiang.xservice.basic.utils;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SSHManager {
+ private static final ConcurrentHashMap sessionMap = new ConcurrentHashMap<>();
+
+ public static void createTunnel(String key, String sshHost, int sshPort,
+ String sshUser, String sshPassword,
+ int localPort, String remoteHost, int remotePort) throws Exception {
+ if (sessionMap.containsKey(key) && sessionMap.get(key).isConnected()) {
+ return; // 已存在
+ }
+ JSch jsch = new JSch();
+ Session session = jsch.getSession(sshUser, sshHost, sshPort);
+ session.setPassword(sshPassword);
+
+ java.util.Properties config = new java.util.Properties();
+ config.put("StrictHostKeyChecking", "no");
+ session.setConfig(config);
+
+ session.connect();
+ session.setPortForwardingL(localPort, remoteHost, remotePort);
+
+ sessionMap.put(key, session);
+ System.out.println("SSH Tunnel for [" + key + "] established.");
+ }
+
+ public static void closeTunnel(String key) {
+ Session session = sessionMap.get(key);
+ if (session != null && session.isConnected()) {
+ session.disconnect();
+ sessionMap.remove(key);
+ System.out.println("SSH Tunnel for [" + key + "] closed.");
+ }
+ }
+}
diff --git a/xservice-message-starter/pom.xml b/xservice-message-starter/pom.xml
index 91631df..7ec39ba 100644
--- a/xservice-message-starter/pom.xml
+++ b/xservice-message-starter/pom.xml
@@ -10,7 +10,7 @@
xservice-message-starter
- 1.1
+ 2.0
17
@@ -22,7 +22,7 @@
com.xiang
xservice-common
- 1.0
+ 1.2
diff --git a/xservice-message-starter/src/main/java/com/xiang/xservice/basic/xservice/dingTalk/service/DingTalkService.java b/xservice-message-starter/src/main/java/com/xiang/xservice/basic/xservice/dingTalk/service/DingTalkService.java
index 132dcb7..a24b972 100644
--- a/xservice-message-starter/src/main/java/com/xiang/xservice/basic/xservice/dingTalk/service/DingTalkService.java
+++ b/xservice-message-starter/src/main/java/com/xiang/xservice/basic/xservice/dingTalk/service/DingTalkService.java
@@ -12,6 +12,7 @@ import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.xiang.xservice.basic.xservice.dingTalk.enums.DingTalkUrlEnum;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -46,53 +47,40 @@ public class DingTalkService {
private static final String CLIENT_SECRET = "wyapsH6y8P1K_wuTPKGKwG0mquj1uth9Dxn6HcRpta3sh8Syukl0C8nOmR1PeBzs";
- private static final String GRANT_TYPE = "client_credentials";
-
- private static final String USER_ID = "450841600726084717";
-
- private static final String MSG_TYPE = "text";
+ private static final String MSG_TYPE_TEXT = "text";
/**
- * 自定义机器人token
- */
- private static final String CUSTOM_ROBOT_TOKEN = "4709b708d961846e0aee523c5abc3b67e8fa424ee292501d85efd4e504f15a8b";
-
- /**
- * 密钥
- */
- private static final String SECRET = "SEC768ed578c0fb31a9aec84b1c1db4f195f5aca203985bbb9d549e23e41c8874d1";
-
- /**
- * 发送机器人消息
- * @param msg
+ * 发送机器人消息到指定的群
+ * @param robotSecret 机器人密钥
+ * @param robotToken 机器人token
+ * @param userIds @对象
+ * @param msg 消息内容
* @return
* @throws Exception
*/
- public String sendRobotMessage(String msg) throws Exception {
+ public String sendRobotMessage(String robotSecret, String robotToken, List userIds, String msg) throws Exception {
Long timestamp = System.currentTimeMillis();
- String stringToSign = timestamp + "\n" + SECRET;
+ String stringToSign = timestamp + "\n" + robotSecret;
Mac mac = Mac.getInstance("HmacSHA256");
- mac.init(new SecretKeySpec(SECRET.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
+ mac.init(new SecretKeySpec(robotSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
String sign = URLEncoder.encode(Base64.getEncoder().encodeToString(signData), StandardCharsets.UTF_8);
//sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?sign=" + sign + "×tamp=" + timestamp);
OapiRobotSendRequest req = new OapiRobotSendRequest();
- /**
- * 发送文本消息
- */
+
//定义文本内容
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(msg);
//定义 @ 对象
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
- at.setAtUserIds(List.of(USER_ID));
+ at.setAtUserIds(userIds);
//设置消息类型
- req.setMsgtype("text");
+ req.setMsgtype(MSG_TYPE_TEXT);
req.setText(text);
req.setAt(at);
- OapiRobotSendResponse rsp = client.execute(req, CUSTOM_ROBOT_TOKEN);
+ OapiRobotSendResponse rsp = client.execute(req, robotToken);
return rsp.getBody();
}
@@ -110,7 +98,7 @@ public class DingTalkService {
OapiChatSendRequest.Text text = new OapiChatSendRequest.Text();
text.setContent(message);
msg.setText(text);
- msg.setMsgtype("text");
+ msg.setMsgtype(MSG_TYPE_TEXT);
req.setMsg(msg);
OapiChatSendResponse rsp = client.execute(req, token);
log.info("[DingTalk] send chat message, req:{}, token:{}, response:{}", JSONObject.toJSONString(req), token, JSONObject.toJSONString(rsp));
@@ -133,7 +121,7 @@ public class DingTalkService {
req.setUseridList(userId);
req.setToAllUser(false);
OapiMessageCorpconversationAsyncsendV2Request.Msg obj1 = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
- obj1.setMsgtype(MSG_TYPE);
+ obj1.setMsgtype(MSG_TYPE_TEXT);
OapiMessageCorpconversationAsyncsendV2Request.Text obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Text();
obj2.setContent(message);
obj1.setText(obj2);
diff --git a/xservice-mysql-starter/pom.xml b/xservice-mysql-starter/pom.xml
index 0eebc0a..9cdeee6 100644
--- a/xservice-mysql-starter/pom.xml
+++ b/xservice-mysql-starter/pom.xml
@@ -10,11 +10,19 @@
xservice-mysql-starter
- 1.1
+ 2.0
17
17
UTF-8
+
+
+ com.xiang
+ xservice-common
+ 1.3
+
+
+
\ No newline at end of file
diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java
index 1a99752..0f27f78 100644
--- a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java
+++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java
@@ -29,7 +29,7 @@ public class DynamicDataSourceConfig {
targetDataSources.put(key, builder.build());
});
- DynamicRoutingDataSource routing = new DynamicRoutingDataSource();
+ DynamicRoutingDataSource routing = new DynamicRoutingDataSource(props);
routing.setDefaultTargetDataSource(targetDataSources.get(props.getPrimary()));
routing.setTargetDataSources(targetDataSources);
return routing;
diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java
index 1eb20bd..36d95f3 100644
--- a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java
+++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java
@@ -12,5 +12,12 @@ public class DataSourceProperty {
private String username;
private String password;
private String driverClassName = "com.mysql.cj.jdbc.Driver";
-
+ private Boolean sshConnect;
+ private String sshHost;
+ private Integer sshPort = 22;
+ private String sshUser;
+ private String sshPassword;
+ private Integer localPort; // 本地转发端口
+ private String remoteHost; // 远端数据库 host
+ private Integer remotePort; // 远端数据库 port
}
diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java
index f058af8..ddff2ae 100644
--- a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java
+++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java
@@ -1,11 +1,37 @@
package com.xiang.xservice.mysql.service;
+import com.xiang.xservice.basic.utils.SSHManager;
import com.xiang.xservice.mysql.config.DynamicDataSourceContext;
+import com.xiang.xservice.mysql.entity.DataSourceProperty;
+import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+import com.xiang.xservice.mysql.entity.DynamicDataSourceProperties;
+@RequiredArgsConstructor
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
+
+ private final DynamicDataSourceProperties dynamicDataSourceProperties;
+
@Override
protected Object determineCurrentLookupKey() {
- return DynamicDataSourceContext.get();
+ String key = DynamicDataSourceContext.get();
+ DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(key);
+ if (Boolean.TRUE.equals(dataSourceProperty.getSshConnect())) {
+ try {
+ SSHManager.createTunnel(
+ key,
+ dataSourceProperty.getSshHost(),
+ dataSourceProperty.getSshPort(),
+ dataSourceProperty.getSshUser(),
+ dataSourceProperty.getSshPassword(),
+ dataSourceProperty.getLocalPort(),
+ dataSourceProperty.getRemoteHost(),
+ dataSourceProperty.getRemotePort()
+ );
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to establish SSH tunnel for " + key, e);
+ }
+ }
+ return key;
}
}
diff --git a/xservice-schedule-starter/pom.xml b/xservice-schedule-starter/pom.xml
index 55cf4e8..b5fb3ee 100644
--- a/xservice-schedule-starter/pom.xml
+++ b/xservice-schedule-starter/pom.xml
@@ -22,7 +22,7 @@
com.xiang
xservice-common
- 1.0
+ 1.2