通过SSH隧道连接远程Oracle数据库失败问题求助
SSH隧道连接Oracle数据库的Java代码问题
我用数据库管理器通过SSH隧道连接远程Oracle数据库完全正常,但用Java代码复现时遇到了连接失败的问题。
我的Java代码
public void afterPropertiesSet() throws Exception { Session session = null; try { session = new JSch().getSession("********","1x.xx.xx.xx"); session.setPassword("*********"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); session.setPortForwardingL(1521,"xx.xx.yy.yy",1521); System.out.println("port forwarding completed"); Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//xx.xx.yy.yy:1521/db","********","********"); System.out.println(conn.getMetaData().getUserName()); }catch (Exception e){ e.printStackTrace(); }finally { if(session!=null) { session.disconnect(); } } }
遇到的报错情况
- 原代码运行时,报错:
java.sql.SQLException: ORA-12541: Cannot connect. No listener at host xx.xx.yy.yy port 1521. (CONNECTION_ID=wIOJk+zFTYCI4FR7XNsHew==)
- 将端口改为1520(主机不变),报错:
Caused by: oracle.net.ns.NetException: ORA-12541: Cannot connect. No listener at host localhost port 1520. (CONNECTION_ID=On8tBIXKQCu40izLoOLsRg==)
- 将驱动主机改为localhost/本地实际IP(端口不变),报错:
Caused by: oracle.net.ns.NetException: ORA-12541: Cannot connect. No listener at host localhost port 1520. (CONNECTION_ID=o8/105qIRG+N9zBuyiaMZg==)
问题分析与修复
核心问题
- JDBC连接字符串错误:你已经通过SSH把本地端口映射到了远程数据库,但代码里还是直接访问远程主机地址,等于没走SSH隧道。
- 可能存在本地端口冲突:如果本地已经有Oracle监听占用了1521端口,端口转发会静默失败,导致连接不上。
修正后的代码
public void afterPropertiesSet() throws Exception { Session session = null; try { // 建立SSH跳板连接 session = new JSch().getSession("你的SSH用户名","跳板机IP"); session.setPassword("你的SSH密码"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 用未被占用的本地端口(比如1520)映射到远程数据库地址和端口 int localForwardPort = 1520; String remoteDbHost = "xx.xx.yy.yy"; int remoteDbPort = 1521; session.setPortForwardingL(localForwardPort, remoteDbHost, remoteDbPort); System.out.println("端口转发完成,本地端口:" + localForwardPort); // JDBC连接本地转发的端口,而不是远程主机 Class.forName("oracle.jdbc.OracleDriver"); String jdbcUrl = "jdbc:oracle:thin:@//localhost:" + localForwardPort + "/db"; Connection conn = DriverManager.getConnection(jdbcUrl, "数据库用户名", "数据库密码"); System.out.println(conn.getMetaData().getUserName()); } catch (Exception e) { e.printStackTrace(); } finally { if(session != null) { session.disconnect(); } } }
额外检查项
- 确认SSH跳板机可以正常ping通并访问远程数据库的1521端口
- 用
netstat -ano(Windows)或lsof -i :1520(Linux/Mac)检查本地1520端口是否被占用 - 确保项目中依赖的JSch版本与Java环境兼容
内容的提问来源于stack exchange,提问作者Akash Jain
相关产品推荐
相关产品推荐

