You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SSHJ从SFTP下载BAK文件至类路径供MSSQLServerContainer加载失败排查

解决MSSQLServerContainer无法识别类路径中新下载BAK文件的问题

这个错误的核心原因是Java类加载器不会自动扫描运行时新增的类路径资源:src/test/resources是源码目录,实际运行时类加载器读取的是编译后复制到target/test-classes的资源;而且即使你把文件写到src/test/resources,已启动的类加载器也不会重新扫描这个目录来发现新文件。下面是几个可行的解决方案:

方案1:直接下载到类加载器实际读取的目录

最直接的办法是跳过源码目录,把BAK文件直接下载到target/test-classes——这是类加载器真正会读取的资源目录。修改你的SSHJ代码中的目标路径:

final SSHClient ssh = new SSHClient();
establishConnection(ssh);
SFTPClient sftp = ssh.newSFTPClient();
List<RemoteResourceInfo> files = sftp.ls("public");
for (RemoteResourceInfo file : files) {
    String remoteServerFileLocation = file.getPath();
    // 直接下载到target/test-classes,类加载器能立即识别
    sftp.get(remoteServerFileLocation, "target/test-classes");
}
sftp.close();
ssh.disconnect();

这样下载完成后,类加载器可以直接找到文件,不需要额外刷新操作,原有的withClasspathResourceMapping代码可以保持不变。

方案2:触发构建工具同步资源到target

如果你需要保持src/test/resources目录的同步(比如后续需要提交文件到版本控制),可以在下载完成后执行构建工具的资源复制命令,把src目录的新文件同步到target。

Maven项目示例:

// 下载完成后执行Maven的process-resources命令
ProcessBuilder pb = new ProcessBuilder("mvn", "process-test-resources");
pb.directory(new File(System.getProperty("user.dir"))); // 指向项目根目录
Process process = pb.start();
int exitCode = process.waitFor();
if (exitCode != 0) {
    throw new RuntimeException("Failed to sync test resources to target directory");
}

Gradle项目示例:

ProcessBuilder pb = new ProcessBuilder("gradle", "processTestResources");
pb.directory(new File(System.getProperty("user.dir")));
Process process = pb.start();
int exitCode = process.waitFor();
if (exitCode != 0) {
    throw new RuntimeException("Failed to sync test resources to target directory");
}

执行完这个命令后,src/test/resources中的新文件会被复制到target/test-classes,类加载器就能找到它了。

方案3:绕开类加载器,用文件系统路径绑定

另一种思路是不依赖类加载器,直接用磁盘文件路径来绑定到容器。修改容器启动代码,替换withClasspathResourceMapping为withFileSystemBind:

// 构造本地文件对象
File backupFile = new File("src/test/resources/" + BACKUP_FILE_NAME);
// 用文件系统路径绑定,而非类路径资源
xMSSQLServerContainer.withFileSystemBind(
    backupFile.getAbsolutePath(), 
    BACKUP_FILE_PATH, 
    BindMode.READ_ONLY
).start();

这种方式直接读取磁盘上的文件,完全不受类加载器的限制,只要文件下载完成,容器就能立即访问到。


内容的提问来源于stack exchange,提问作者Pradeep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:54:57