我正在将带有Hibernate的Spring Data JPA作为持久性提供程序,与远程MySQL5 Server结合使用,用于定期复制内部数据子集的作业。这项工作(即 quartz 计划的Java应用程序)每天执行一次,大约需要30秒即可完成同步)。出于安全原因,我们不希望打开远程服务器以进行外部(即localhost以外)的直接连接。
我已经看到了使用Jsch通过编程方式建立ssh隧道的示例,但是找不到有关如何将Jsch与spring数据集成的任何资源。我看到的一个问题是我的某些Spring bean(即org.apache.commons.configuration.DatabaseConfiguration)是在应用程序启动时创建的,并且已经需要访问数据源。
我可以在应用程序外部打开ssh隧道,但是它会一直打开,但是我想避免这种情况,因为我每天只需要打开30秒即可。
编辑:
经过研究,我发现了几种建立ssh隧道的方法
A)实现自己的数据源(我扩展了org.springframework.jdbc.datasource.DriverManagerDataSource),然后使用PostContruct和Predestroy通过Jsch设置/关闭ssh隧道
->问题:ssh隧道在应用程序的生命周期内保持打开状态,这不是我想要的
B)实现我自己的驱动程序(扩展了com.mysql.jdbc.Driver),并在连接之前覆盖“connect”以创建ssh隧道
->问题:我无法关闭ssh隧道连接
欢迎任何其他建议
最佳答案
如果您的Spring配置中包含DataSource
bean,则可以创建自己的DataSource
实现,该实现会在尝试使用提供的JDBC URL建立连接之前打开SSH隧道。例如,考虑使用HikariDataSource
的以下配置:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource">
<bean class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">...</bean>
</property>
</bean>
您可以扩展
HikariDataSource
类以提供自己的实现。下面的例子:class TunneledHikariDataSource extends HikariDataSource implements InitializingBean {
private boolean createTunnel = true;
private int tunnelPort = 3306;
public void afterPropertiesSet() {
if(createTunnel) {
// 1. Extract remote host name from the JDBC URL.
// 2. Extract/infer remote tunnel port (e.g. 3306)
// from the JDBC URL.
// 3. Create a tunnel using Jsch and sample code
// at http://www.jcraft.com/jsch/examples/PortForwardingL.java.html
...
}
}
}
然后,实例化自定义类的bean实例,而不是
HikariDataSource
。