diff --git a/pom.xml b/pom.xml
index 5d1c4bc..62d0925 100644
--- a/pom.xml
+++ b/pom.xml
@@ -155,6 +155,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-mysql-starter/pom.xml b/xservice-mysql-starter/pom.xml
index 0eebc0a..ca4504a 100644
--- a/xservice-mysql-starter/pom.xml
+++ b/xservice-mysql-starter/pom.xml
@@ -10,11 +10,19 @@
xservice-mysql-starter
- 1.1
+ 2.0-SNAPSHOT
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;
}
}