Spring 框架 用SSH通道的方式 JDBC连接数据库

前提: 公司数据库,项目都放在 云服务器上跑的,今天为了XXX安全,然后禁止公网访问数据库,如果需要访问 可以通过SSH隧道。

思路: 网上百度了很多,大部分都是写一个DBUtils 工具类,我觉得改动太大了,没采用,看了其它大神的文章,找到了用 监听器的方式,来监听端口,然后映射远程端口 把SSH隧道 当作 类似跳板机 的东西 来使用

 

所以 我们只需要监听本地的 端口 就可以了,一旦监听到了 替换 数据库连接的一些配置就可以了

-------------------------- 开始 动手了

1、需要导入一个第三方的包 帮我们连接SSH

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

2、创建一个类实现 监听器的接口(有servlet自带的 ServletContextListener,也有spring 的 TestExecutionListener ,是有所区别的 暂时留一个坑)

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

@WebListener
public class MyListener implements ServletContextListener {

    private SSHConnection conexionssh;


    public MyListener() {
        super();
    }

    /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("Context initialized ... !");
        try {
            conexionssh = new SSHConnection(); // 监听到了 就装配文件
        } catch (Throwable e) {
            e.printStackTrace(); // error connecting SSH server
        }
    }

    /**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("Context destroyed ... !");
        conexionssh.closeSSH(); // disconnect
    }

}

@WebListener 是servlet3.1之后新增的一个注解,可以不用再web.xml配置监听器

 

3、 装配SSH的 一些配置,继续New一个类

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

public class SSHConnection {
    
    private final static int LOCAl_PORT = 3307;
    private final static int REMOTE_PORT = 3306;
    private final static int SSH_REMOTE_PORT = sshport;
    private final static String SSH_USER = "sshuser";
    private final static String SSH_PASSWORD = "sshpassword";
    private final static String SSH_REMOTE_SERVER = "sshurl";
    private final static String MYSQL_REMOTE_SERVER = "数据库地址";

    private Session sesion; //represents each ssh session

    public void closeSSH() {
        sesion.disconnect();
    }

    public SSHConnection() throws Throwable {
        
        JSch jsch = null;
        jsch = new JSch();
        
        sesion = jsch.getSession(SSH_USER, SSH_REMOTE_SERVER, SSH_REMOTE_PORT);
        sesion.setPassword(SSH_PASSWORD);

        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        sesion.setConfig(config);

        sesion.connect(); //ssh connection established!

        //by security policy, you must connect through a fowarded port
        sesion.setPortForwardingL(LOCAl_PORT, MYSQL_REMOTE_SERVER, REMOTE_PORT);

    }
}

 

4、数据库的配置 稍微修改下 ,只需要修改地址 

jdbc.url=jdbc:mysql://123456.mysql.rds.aliyuncs.com:3306/数据库名称?useUnicode=true&characterEncoding=utf8
替换为 
jdbc.url=jdbc:mysql://127.0.0.1:3307/数据库名称?useUnicode\=true&characterEncoding\=utf8

127.0.0.1 表示本地  3307表示 本地的端口(可随意指定 3300 也可以 等等) 

 

然后就OK了。。 启动项目 跑起来 飞吧。。。。。

 

 

但是,但是  ,细心的你会发现,如果是junit 单元测试,依然行不通, 因为 我的容器是内嵌的Jetty类似于Tomcat ,junit只会读取applicationContext.xml,并不会加载 监听器, 所以 现在开始填补选择继承监听器的坑。

因为junit @Test 是Spring 的东西,So选择监听器的时候可以选择实现Spring的监听器  TestExecutionListener 接口

import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyContextListener implements  TestExecutionListener {

    private SSHConnection conexionssh;


    public MyContextListener() {
        super();
    }

    /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("Context initialized ... !");
        try {
            conexionssh = new SSHConnection();
        } catch (Throwable e) {
            e.printStackTrace(); // error connecting SSH server
        }
    }

    /**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("Context destroyed ... !");
        conexionssh.closeSSH(); // disconnect
    }

    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {

    }

    @Override
    public void prepareTestInstance(TestContext testContext) throws Exception {
        System.out.println("Context initialized ... !");
        try {
            conexionssh = new SSHConnection();
        } catch (Throwable e) {
            e.printStackTrace(); // error connecting SSH server
        }

    }

    @Override
    public void beforeTestMethod(TestContext testContext) throws Exception {

    }

    @Override
    public void afterTestMethod(TestContext testContext) throws Exception {

    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {

    }
}

然后在 test类配置

@RunWith(SpringJUnit4ClassRunner.class) //启动必备
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) //启动的时候读取文件
@TestExecutionListeners(listeners = { MyContextListener.class, DependencyInjectionTestExecutionListener.class }) //启动的时候获取监听器
public class TestEmployee {

   xxx 要测试的东西

}

 

然后就OK了。。 单元测试 跑起来 飞吧。。。。。

 

 

但是,但是,但是 我的项目 又启动不起来了。。。 

为什么呢,因为 项目已启动 首先读取web.xml配置 里面会配置<servlet> 读取application.xml</servlet> 然后配置 spring的一些东西, 数据库连接池,等等。。。

在配置数据库连接池的时候,因为是JDBC链接的,所以要读取 db.properties文件,但是这时候 url地址 是 本地的。。 监听器又没办法启动, 所以导致数据库连接失败 。。。  

Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server. Attempted reconnect 3 times. Giving up.)

唉 这又是一个坑(暂时 没时间研究解决方案了,待我成为大神 再更新吧...)

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值