引言
在项目开发过程中,遇到了连接数据库时需要使用ssh公钥的情况。在本地使用navicat可以直接通过可视化界面去进行ssh的连接,但是在java中无法直接去进行连接。
后来经过查询资料,发现必须要在java中编写相关配置文件后才可以正常连接。
问题解决
原理:程序在本机创建ssh连接
,连接到ssh server,然后再发送数据库操作指令,指令会被转发到目标数据库服务器上,返回操作结果
**前提:**项目已经配置好mysql连接所需要参数
**注意:**我演示的是使用ssh的公钥模式进行连接,如果需要使用密码模式进行连接,需要打开和关闭某些注释
-
引入依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
-
编写ssh连接配置类
package com.lzj.config;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.util.Properties;
public class SSHConnectionConfig {
private String SSH_PATH_FILE_KNOWN_HOSTS = "C:\\Users\\86158\\.ssh\\known_hosts";
private String SSH_PATH_FILE_PRIVATE_KEY = "**********************************";
private String SSH_USER = "******";
private String SSH_REMOTE_SERVER = "65.115.26.30";
private Integer SSH_REMOTE_PORT = 22;
private String MYSQL_REMOTE_SERVER = "127.0.0.1";
private Integer LOCAl_PORT = 3307;
private Integer REMOTE_PORT = 3309;
private Session session;
public void closeSSH() {
session.disconnect();
}
public void createSSH() throws JSchException {
JSch jSch = new JSch();
jSch.setKnownHosts(SSH_PATH_FILE_KNOWN_HOSTS);
jSch.addIdentity(SSH_PATH_FILE_PRIVATE_KEY);
session = jSch.getSession(SSH_USER, SSH_REMOTE_SERVER, SSH_REMOTE_PORT);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
session.setPortForwardingL(LOCAl_PORT, MYSQL_REMOTE_SERVER, REMOTE_PORT);
}
}
-
编写监听器
注意:
- Listener类使用@WebListener注解;
- SpringBoot的启动类需要增加
@ServletComponentScan
用于扫描加载Listener类;
经过我的尝试,发现如果使用了@Component
注解,就算不使用@WebListener
也同样可以完成监听功能
package com.lzj.config;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@Component
@WebListener
public class MyContextListener implements ServletContextListener {
private SSHConnectionConfig sshConnectionConfig;
public MyContextListener() {
super();
}
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Context initialized ... !");
try {
sshConnectionConfig = new SSHConnectionConfig();
sshConnectionConfig.createSSH();
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Context destroyed ... !");
sshConnectionConfig.closeSSH();
}
}
-
注意可能需要修改你的mysql连接配置
可以看见我的的url中的localhost:3307
,这个ip和端口号是根据你编写的ssh配置类
中MYSQL_REMOTE_SERVER
和LOCAl_PORT
来的,你可能需要进行修改
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ******
url: jdbc:mysql://localhost:3307/leopard-vendor_cloud?autoReconnect=true&useUnicode=true&useSSL=false
-
测试
编写一个测试类测试数据库的连接
package com.lzj;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.sql.DataSource;
import java.sql.SQLException;
@SpringBootTest(classes = SpringbootDetabaseApplication.class)
@RunWith(SpringRunner.class)
public class InitTest {
@Autowired
private DataSource dataSource;
@Test
public void testDataSource() throws SQLException {
System.out.println(dataSource.getConnection());
}
}
测试结果如下:
可以发现控制台正常输出了连接相关信息
总结
**注意:**数据库连接地址由原来的123.mysql.com:3306改为127.0.0.1:3307,这样子,ssh连接会为每一个127.0.0.1:3307上的操作转发到123.mysql.com:3306上去,便可以正常操作数据库了。ssh连接的创建,可以采用私钥的方式,亦可以采用用户名密码的方式。
参考文章
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)