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

Spring Boot整合Jetty时无法读取Jar内keystore.jks的问题

解决Jar包内Keystore文件无法访问的问题

这个问题我之前在Spring Boot+Jetty项目里也踩过坑!核心原因很简单:Jar包内的资源并不是磁盘上的独立物理文件,你用getResource().getFile()拿到的路径是Jar内部的虚拟路径(比如file:/root/project/my_jar.jar!/keystore.jks),这种格式的路径File类根本识别不了,所以exists()返回false是必然的。

正确的解决方案:用输入流加载Jar内资源

Jetty的SslContextFactory支持直接通过输入流加载密钥库,不需要依赖文件路径。我们可以改用getResourceAsStream()获取Jar内资源的输入流,然后传递给SslContextFactory。

修改后的代码如下:

@Bean(name = "containerCustomizer") 
public EmbeddedServletContainerCustomizer containerCustomizer() { 
    return (container -> ((JettyEmbeddedServletContainerFactory) container).addServerCustomizers(
        new JettyServerCustomizer() { 
            @Override 
            public void customize(Server server) { 
                // HTTP 连接器配置
                ServerConnector connector = new ServerConnector(server); 
                connector.setPort(80); 

                // HTTPS 连接器配置
                SslContextFactory sslContextFactory = new SslContextFactory(); 
                try (InputStream keyStoreStream = getClass().getClassLoader().getResourceAsStream("keystore.jks")) {
                    // 直接用输入流加载密钥库
                    sslContextFactory.setKeyStoreInputStream(keyStoreStream);
                    sslContextFactory.setKeyStorePassword("password");
                } catch (IOException e) {
                    // 捕获资源加载异常,根据业务需求处理,这里直接抛出运行时异常
                    throw new RuntimeException("Failed to load keystore from JAR file", e);
                }

                HttpConfiguration https = new HttpConfiguration(); 
                https.addCustomizer(new SecureRequestCustomizer()); 
                ServerConnector sslConnector = new ServerConnector(server, 
                    new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), 
                    new HttpConnectionFactory(https)); 
                sslConnector.setPort(443); 

                server.setConnectors(new Connector[] {connector, sslConnector}); 
            } 
        })); 
}

关键说明:

  • getResourceAsStream()是访问Jar内部资源的标准方式,它会直接读取Jar包内的资源内容,完全绕过了文件系统的限制。
  • 用try-with-resources语法包裹输入流,确保资源自动关闭,避免内存泄漏。

备选方案:如果你的Jetty版本不支持输入流加载

如果你的Jetty版本比较旧,SslContextFactory没有setKeyStoreInputStream()方法,可以先把Jar内的资源复制到临时文件,再用临时文件的路径配置:

// 旧版Jetty的兼容方案:复制到临时文件
try (InputStream keyStoreStream = getClass().getClassLoader().getResourceAsStream("keystore.jks")) {
    File tempKeystore = File.createTempFile("temp-keystore", ".jks");
    tempKeystore.deleteOnExit(); // 程序退出时自动删除临时文件,避免残留
    Files.copy(keyStoreStream, tempKeystore.toPath(), StandardCopyOption.REPLACE_EXISTING);
    
    sslContextFactory.setKeyStorePath(tempKeystore.getAbsolutePath());
    sslContextFactory.setKeyStorePassword("password");
} catch (IOException e) {
    throw new RuntimeException("Failed to load and copy keystore", e);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:45:43