jdbc或springboot通过ssh连接数据库

备注

通过ssh连接的数据库通常需要部署到对应的环境才能连接,但这样就不方便本地debug,使用jsch就可以很方便的连接需要通过ssh连接的数据库了。

Maven

添加maven

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.53</version>
</dependency>

一、jdbc通过ssh连接数据库

如果只是低频次的查询其它需要ssh连接的数据库,直接用jdbc比较方便

    /**
     * jdbc+JSch连接需要ssh连接的数据库
     * @param sql sql语句
     * @param sshHost 服务器地址
     * @param sshPort 服务器端口
     * @param sshUsername 服务器用户名
     * @param sshPassword 服务器密码
     * @param dbHost 数据库地址
     * @param dbPort 数据库端口
     * @param dbUsername 数据库用户名
     * @param dbPassword 数据库密码
     * @param dbName 数据库库名
     * @return 查询结果
     */
    public JSONArray connectionSshMysql(String sql,
                                        String sshHost, int sshPort, String sshUsername, String sshPassword,
                                        String dbHost, int dbPort, String dbUsername, String dbPassword, String dbName) {
        int localPort = 5678; // 本地临时端口
        try {
            // 1.建立SSH连接
            JSch jsch = new JSch();
            Session session = jsch.getSession(sshUsername, sshHost, sshPort);
            session.setPassword(sshPassword);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            session.setPortForwardingL(localPort, dbHost, dbPort);
            // 2.建立数据库连接
            String dbUrl = "jdbc:mysql://127.0.0.1:" + localPort + "/" + dbName + "?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8";
            Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
            // 3.获取数据库操作对象
            Statement statement = connection.createStatement();
            // 4.执行sql
            ResultSet resultSet = statement.executeQuery(sql); // 查
            //int affectedRows = statement.executeUpdate(sql); // 增删改
            // 4.1将查询到的数据转为JSON字符串
            JSONArray jsonArray = new JSONArray();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                JSONObject jsonObject = new JSONObject();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = metaData.getColumnLabel(i);
                    String columnValue = resultSet.getString(i);
                    jsonObject.put(columnName, columnValue);
                }
                jsonArray.add(jsonObject);
            }
            // 5.关闭数据库连接
            connection.close();
            session.delPortForwardingL(localPort);
            session.disconnect();
            // 6.返回执行sql结果
            return jsonArray;
            //return affectedRows;
        } catch (JSchException | SQLException e) {
            e.printStackTrace();
            return new JSONArray();
        }
    }


二、springboot通过ssh连接数据库

如果是高频次的连接需要通过ssh连接的数据库,那么使用该方法比较合适

1.添加配置类

import org.springframework.context.annotation.Import;
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(SSHConfigDefinitionRegistrar.class)
public @interface EnableSSH {

    String[] profiles() default "default";

    String sshHost() default "";

    int sshPort() default 22;

    String sshUser() default "root";

    String sshPassword() default "";

    String remoteHost() default "";

    int remotePort() default 3306;

    int localPort() default 3307;

}
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.stereotype.Component;

import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

@Component
public class SSHConfigDefinitionRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private static String activeProfile = "default";

    @Override
    public void setEnvironment(Environment environment) {
        String[] activeProfiles = environment.getActiveProfiles();
        if (activeProfiles != null && activeProfiles.length > 0) activeProfile = activeProfiles[0];
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        System.out.println("开始连接");
        StandardAnnotationMetadata meta = (StandardAnnotationMetadata) metadata;
        Class<?> bootClass = meta.getIntrospectedClass();
        EnableSSH enableSSH = bootClass.getAnnotation(EnableSSH.class);
        if (enableSSH == null) return;
        String[] profiles = enableSSH.profiles();
        List<String> list = Arrays.asList(profiles);
        if (!list.contains(activeProfile)) {
            return;
        }
        SSHConnection connection = new SSHConnection(enableSSH, activeProfile);
        try {
            connection.connect();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("建立连接");
    }

    class SSHConnection implements Closeable {

        private EnableSSH config;
        private String profile;
        private Session session;

        public void connect() throws InterruptedException {
            String sshHost = config.sshHost();
            int sshPort = config.sshPort();
            String sshUser = config.sshUser();
            String sshPassword = config.sshPassword();
            int localPort = config.localPort();
            String remoteHost = config.remoteHost();
            int remotePort = config.remotePort();
            JSch jsch = new JSch();
            Thread thread = new Thread(() -> {
                try {
                    session = jsch.getSession(sshUser, sshHost, sshPort);
                    session.setPassword(sshPassword);
                    Properties config = new Properties();
                    config.put("StrictHostKeyChecking", "no");
                    session.setConfig(config);
                    session.connect();
                    session.setPortForwardingL(localPort, remoteHost, remotePort);
                } catch (JSchException e) {
                    e.printStackTrace();
                }
            });
            thread.start();
            Thread.sleep(1000*30);
        }

        public SSHConnection(EnableSSH enableSshConfigs, String profile) {
            this.config = enableSshConfigs;
            this.profile = profile;
        }

        @Override
        public void close() throws IOException {
            if (session != null) session.disconnect();
        }
    }
}

2.修改启动类

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.PostConstruct;
import java.util.Properties;

@SpringBootApplication
@MapperScan("com.xxx.xxx.mapper")
public class Application {

    private static Session session;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    //用于本地测试时连接ssh数据库
    @PostConstruct
    public void init() {
        JSch jsch = new JSch();
        Thread thread = new Thread(() -> {
            try {
                session = jsch.getSession(ssh服务器用户名, ssh服务器地址, ssh服务器端口);
                session.setPassword(ssh服务器密码);
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no");
                session.setConfig(config);
                session.connect();
                session.setPortForwardingL(自定义端口号, 数据库地址, 数据库端口);
            } catch (JSchException e) {
                e.printStackTrace();
            }
        });
        thread.start();
    }
}

3.修改配置文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:自定义端口号/库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    username: 数据库用户名
    password: 数据库密码
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值