Springboot通过跳板机使用SSH连接数据库

小记:因为近期新开发的新系统需要调用已有老系统的数据库,但数据库服务器的所有访问都需要通过跳板机连接过去,所以只能通过SSH桥接转发的方式进行数据库访问。

原理:程序在本机创建ssh连接,连接到ssh server,然后再发送数据库操作指令,指令会被转发到目标数据库服务器上,返回操作结果。

1. 项目引入依赖

<!--ssh链接数据库-->
<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.55</version>
</dependency>

2. 创建SSH的连接工具类


import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.sql.*;
import java.util.Properties;

/**
 1. @Date: 2021/2/26 10:34
 2. @Author: Yan
 3. @Description: ssh跳板机桥接远端数据库
 */
@Component
public class SSHConnection {
	//数据库连接对象
	private Connection ct = null;
	//SSH回话对象
	private Session session;
	//SSH连接配置
	private final static String SSH_REMOTE_SERVER = "192.168.0.99";
	private final static int SSH_REMOTE_PORT = 22;
	private final static String SSH_USER = "sshuser";
	private final static String SSH_PASSWORD = "sshpwd";

	//目标数据库的连接信息
	private final static String MYSQL_REMOTE_SERVER = "cms.mysql.aliyuncs.com";
	private final static int MYSQL_REMOTE_PORT = 3306;

	//本机的数据库的连接信息(测试使用)
	private final static String URL = "jdbc:mysql://127.0.0.1:3307/cms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull";
	private final static int LOCAl_PORT = 3307;
	private final static String USERNAME = "root";
	private final static String PASSWORD = "root";

	/**
	 * 建立SSH连接
	 */
	public void init() {
		try {
			//创建SSH回话
			JSch jsch = new JSch();
			session = jsch.getSession(SSH_USER, SSH_REMOTE_SERVER, SSH_REMOTE_PORT);
			session.setPassword(SSH_PASSWORD);
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);
			session.connect();
			//打印SSH服务器版本信息
			System.out.println(session.getServerVersion());
			//将本地3307端口的请求转发到目标地址的3306端口
			session.setPortForwardingL(LOCAl_PORT, MYSQL_REMOTE_SERVER, MYSQL_REMOTE_PORT);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 断开SSH连接
	 */
	public void destroy() {
		this.session.disconnect();
	}

	/**
	 * 获取数据库链接(测试使用)
	 *
	 * @return
	 */
	public Connection getConnection() {
		try {
			return ct = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ct;
	}

	//测试使用
	public static void main(String[] args) throws SQLException {
		SSHConnection sshConnection = new SSHConnection();
		sshConnection.init();
		Connection connection = sshConnection.getConnection();
		PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM goods_spu limit 10");
		ResultSet rs = preparedStatement.executeQuery();
		System.out.println(rs);
		while (rs.next()) {
			//获取id列数据
			String id = rs.getString("id");
			//获取goodsName列数据
			String goodsName = rs.getString("goods_name");
			//输出结果
			System.out.println(id + "\t" + goodsName);
		}
		rs.close();
		connection.close();
		sshConnection.destroy();
	}
}

3. 设置监听自动创建SSH连接


import com.xxx.delivery.config.SSHConnection;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@Slf4j
@Component
@WebListener
public class DataSourceContextListener implements ServletContextListener {

	public DataSourceContextListener() {
		super();
	}

	/**
	 * @see ServletContextListener#contextInitialized(ServletContextEvent)
	 */
	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		try {
			SSHConnection.init();
			log.info("SSH连接初始化成功");
		} catch (Throwable e) {
			log.error("SSH连接异常:{}", e.getLocalizedMessage());
		}
	}

	/**
	 * @see ServletContextListener#contextDestroyed(ServletContextEvent)
	 * 关闭ssh连接
	 */
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		SSHConnection.destroy();
		log.info("SSH连接关闭");
	}
}

4. 启动类中加上@ServletComponentScan注解(可以省略)

说明:
之前DataSourceContextListener 没有加上@configuration ,SSHConfiguration上没有加@configuration 和@Component,导致项目启动时DataSourceContextListener 不启动,所以后来在启动类上加了@ServletComponentScan注解,项目启动时扫描一遍。
但加上注解之后,就不在需要项目启动时用注解扫描,**因此,这一步可以省略 **。

@SpringBootApplication
@ServletComponentScan
public class AdminApp {
    public static void main(String[] args) {
        SpringApplication.run(AdminApp.class, args);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值