JDBC通过SSH连接远程MySQL报错:Url cannot be null求助
Hey there, let's work through this error you're facing. You've got the SSH tunnel up with JSch, but the JDBC connection is throwing "Url cannot be null"—that almost always means your JDBC URL isn't being properly constructed or passed to the connection method. Let's break down the fixes step by step:
1. First, Construct a Valid JDBC URL
Your code snippet defines all the necessary variables (local port, remote host, DB credentials) but I don't see where you're building the actual JDBC URL. Since you're using a local port forward (mapping your local 5656 to the remote MySQL's 3306), your URL should point to localhost with that local port.
Here's how to build it correctly:
// Replace "your_database_name" with your actual database name String jdbcUrl = "jdbc:mysql://localhost:" + lport + "/your_database_name?serverTimezone=UTC&useSSL=false";
- For MySQL 8.0+, the
serverTimezoneparameter is required to avoid timezone errors. - Adjust
useSSLbased on your security requirements.
2. Ensure the URL is Used in Your DB Connection
Once you've constructed the URL, you need to pass it to DriverManager.getConnection() (or your DataSource setup). If you're missing this step, the URL will be null, hence the error.
Add this line after setting up the SSH tunnel:
Connection dbConnection = DriverManager.getConnection(jdbcUrl, dbuserName, dbpassword);
3. Verify Your SSH Port Forwarding is Working
Even if JSch says the SSH connection is successful, double-check that the port forwarding is actually active. You can test this with a simple command:
telnet localhost 5656
If it connects, your tunnel is working. If not, make sure you've added this line in your JSch code to enable the forward:
// This maps local port lport to remote rhost:rport session.setPortForwardingL(lport, rhost, rport);
Also, ensure your SSH session stays connected while you're using the database connection—don't disconnect it before making the JDBC call.
Full Working Code Snippet
Here's a complete example tying together the SSH tunnel and JDBC connection, incorporating the fixes above:
import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SSHDBConnector { public void connectSSHAndDB() { int lport = 5656; String rhost = "your_remote_mysql_host"; // Replace with actual host String sshHost = "your_ssh_server_host"; // Replace with actual SSH host int rport = 3306; String sshUser = "your_ssh_username"; // Replace with actual SSH user String sshPassword = "your_ssh_password"; // Replace with actual SSH password String dbuserName = "your_mysql_username"; // Replace with actual DB user String dbpassword = "your_mysql_password"; // Replace with actual DB password String dbName = "your_database_name"; // Replace with actual DB name Session session = null; Connection dbConn = null; try { // Initialize JSch and SSH session JSch jsch = new JSch(); session = jsch.getSession(sshUser, sshHost, 22); // Default SSH port is 22; adjust if needed session.setPassword(sshPassword); // Skip host key check (not recommended for production—add trusted keys instead) session.setConfig("StrictHostKeyChecking", "no"); session.connect(); System.out.println("SSH connection established successfully"); // Set up local port forwarding session.setPortForwardingL(lport, rhost, rport); System.out.println("Port forwarding active: localhost:" + lport + " -> " + rhost + ":" + rport); // Construct JDBC URL String jdbcUrl = "jdbc:mysql://localhost:" + lport + "/" + dbName + "?serverTimezone=UTC&useSSL=false"; System.out.println("Constructed JDBC URL: " + jdbcUrl); // Load MySQL driver (optional for newer JDBC versions, but safe to include) Class.forName("com.mysql.cj.jdbc.Driver"); // Establish database connection dbConn = DriverManager.getConnection(jdbcUrl, dbuserName, dbpassword); System.out.println("Database connection successful!"); // Execute your database operations here... } catch (JSchException | ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { // Clean up resources try { if (dbConn != null && !dbConn.isClosed()) { dbConn.close(); System.out.println("Database connection closed"); } } catch (SQLException e) { e.printStackTrace(); } if (session != null && session.isConnected()) { session.disconnect(); System.out.println("SSH session disconnected"); } } } }
Quick Additional Checks
- Make sure you have the MySQL JDBC driver added to your project (e.g., via Maven or a local JAR file).
- Ensure the local port 5656 isn't being used by another application—if it is, pick a different unused port.
- For production environments, remove the
StrictHostKeyCheckingbypass and configure trusted host keys for security.
内容的提问来源于stack exchange,提问作者EJ_Ozyazgan

