通过Java使用SSH访问远程树莓派4上的MariaDB服务器问题咨询
问题排查与修复方案
现有代码核心问题
- SSH核心配置为空:
sshUser、sshHost两个参数均为空白值,需要填入树莓派对应的SSH登录用户名(默认通常为pi)、树莓派的可访问IP地址(同局域网下填本地IP,跨网填公网映射地址) - 私钥路径解析失败:JSch无法识别
~作为用户目录的简写,jsch.addIdentity("~/.ssh/id_rsa")需要替换为本地id_rsa私钥文件的绝对路径,比如Windows环境为C:/Users/你的用户名/.ssh/id_rsa,macOS/Linux环境为/home/你的用户名/.ssh/id_rsa - 未关闭主机密钥校验:JSch默认会校验目标主机的SSH指纹,本地未提前存储树莓派指纹时会直接抛出连接异常,个人开发场景可在
session.connect()前添加session.setConfig("StrictHostKeyChecking", "no");关闭校验 - SQL语法错误:INSERT语句缺少
VALUES关键字,且字段名错误使用单引号包裹(单引号仅用于标记字符串值,字段名需用反引号包裹或不加符号),同时直接拼接用户输入存在SQL注入风险,建议替换为PreparedStatement - 资源未释放:SSH会话、数据库连接、SQL执行对象用完后均未关闭,会长期占用树莓派连接资源,也会导致本地资源泄漏
- JDBC连接参数缺失:高版本MariaDB需要在JDBC URL后添加时区、SSL配置,否则会出现连接报错
优化后代码示例
public void actionPerformed(ActionEvent event) { if(event.getSource() == submitButton){ String name = userField.getText(); String email = emailField.getText(); String system = systemField.getText(); String serial = serialField.getText(); String date = dateField.getText(); // 填入你自己的实际配置 int localPort = 6000; String sshUser ="pi"; String sshHost = "你树莓派的IP"; String dbHost = "192.168.1.242"; int dbPort = 3306; String dbUser = "root"; String dbPassword = "wacky12"; String driver = "com.mysql.cj.jdbc.Driver"; // 高版本MariaDB用这个驱动类 Session session = null; Connection connection = null; PreparedStatement pstmt = null; try{ JSch jsch = new JSch(); // 替换成你自己的私钥绝对路径 jsch.addIdentity("/home/你的用户名/.ssh/id_rsa"); session = jsch.getSession(sshUser, sshHost, 22); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 固定用6000端口做转发,也可以保留0用随机端口 int forwardedPort = session.setPortForwardingL(localPort, dbHost, dbPort); String url = "jdbc:mysql://localhost:" + forwardedPort + "?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; Class.forName(driver); connection = DriverManager.getConnection(url, dbUser, dbPassword); // 用预编译语句避免SQL注入,且语法更规范 String insert = "insert into LaptopReturns(`name`,`email`,`system`,`serial`,`date`) values(?,?,?,?,?)"; pstmt = connection.prepareStatement(insert); pstmt.setString(1, name); pstmt.setString(2, email); pstmt.setString(3, system); pstmt.setString(4, serial); pstmt.setString(5, date); pstmt.executeUpdate(); System.out.print("Done!"); }catch (Exception e) { e.printStackTrace(); } finally { // 关闭所有资源,注意顺序 try { if(pstmt != null) pstmt.close(); } catch (Exception e) {} try { if(connection != null) connection.close(); } catch (Exception e) {} try { if(session != null) session.disconnect(); } catch (Exception e) {} } } }
SSH连接选型建议
- 高频使用场景:如果你的程序提交数据的频率很高(比如每分钟多次操作),建议程序启动时就建立SSH连接,额外增加断连自动重连逻辑即可,避免每次操作都重复建立SSH连接的额外开销
- 低频使用场景:如果提交操作频次很低(比如每日仅几次操作),建议点击按钮时按需建立连接,操作完成后立即关闭连接,减少树莓派后台空闲连接的资源占用
内容的提问来源于stack exchange,提问作者SierraArgo
相关产品推荐
相关产品推荐

