公司的开发环境已经日式衰微,再加上测试人员测试都在测试环境上,但是测试环境的数据库需要通过ssh隧道才能连接上,于是研究了一波,才有了下文。
首先给出结果:使用 com.jcraft.jsch 提供的ssh转发功能实现:使用servlet监听器在web项目启动时连接到ssh服务器,在初始化dataSource时将数据库连接请求转发到目标数据库,后续所有对数据库的操作都通过转发实现对目标数据库的操作。
过程如图所示:如有问题请指出,感谢。
贴出具体代码:
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
public class SshConnection {
//目标ssh服务器
String username = "xxxx";
String password = "xxxx";
String host = "xxxx";
int port = 22;
//本地监听端口
int local_port = 3307;
//远程数据库地址与端口
String remote_host = "xxxx";
int remote_port = 3306;
Session session;
/**
* 建立SSH连接
*/
public void init() {
try {
JSch jsch = new JSch();
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
session.setPortForwardingL(local_port, remote_host, remote_port);
System.out.println("ssh隧道配置: localhost:" + port + " -> " + remote_host + ":" + remote_port);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 断开SSH连接
*/
public void destroy() {
this.session.disconnect();
}
/**
* 监听器,用于在项目启动时连接ssh服务
*/
@WebListener
@Component
public class SshContextListener implements ServletContextListener {
private SshConnection sshConnection;
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("==========>Context initialized...");
try {
sshConnection = new SshConnection();
sshConnection.init();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("==========>Context destroyed...");
try {
sshConnection.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后数据库如下配置,我这里使用的是Druid连接池
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
#测试环境
username: xxxx
password: xxxx
url: jdbc:mysql://127.0.0.1:3307/xxxx