java - JarFileFactory 缓存 jar 文件

标签 java spring spring-boot urlclassloader

我有 Spring Boot 应用程序,它由 2 个模块组成:前端和 Spring Boot 应用程序项目(前端是 Spring Boot 应用程序的 gradle 依赖项)。

如果我运行 gradle bootRun 应用程序启动并正常工作,那么我会更改一些内容,gradle 会重建项目并替换 frontend.jar。前端仅包含静态资源。它们被添加到类路径中,并且 spring 可以为这些静态文件的请求提供服务。通过构建替换frontend.jar并自动重启后,无法加载spring应用程序资源,发生zip错误,它们在我之前的question中描述过.

我调试应用程序,深入java内部类,发现frontend.jar缓存在JarFileFactory中:

private JarFile getCachedJarFile(URL url) {
    assert Thread.holdsLock(instance);
    JarFile result = fileCache.get(urlKey(url)); // <- fileCache contains my frontend.jar
    ...
}

fileCache 包含我的 jar。在调试中,我尝试在 URLConnection 中禁用此文件的缓存:

   protected URLConnection(URL url) {
    this.url = url;
    if (url == null) {
        this.useCaches = defaultUseCaches;
    } else {
        this.useCaches = getDefaultUseCaches(url.getProtocol()); // <- here I change this.useCaches to false in debugger
    }
}

禁用此文件的缓存后,当前请求工作正常。下一个请求(如果我不在调试器中更改 useCaches)将失败并出现相同的错误。

但是我找不到从我的应用程序中禁用 jar 的缓存的方法(或者在应用程序重新加载时从缓存中一次性删除)。

如何正确清理应用程序的 jar 缓存?或者强制不为我的 jar 使用缓存?或者开发时配置gradle直接使用磁盘上的文件,而不是jar中的文件?

最佳答案

我找到了这个解决方案:

@Component
class StaticResourcesPathProviderComponent {
    @Bean
    @Profile("dev")
    fun getResourcesPathProviderDev() : StaticResourcesPathProvider {
        return object : StaticResourcesPathProvider {
            override fun GetStaticResourcesPath(): String {
                var springAppPath = File(".").getAbsolutePath()

                return "file:///$springAppPath/../frontend-react-components/build/";
        }
    }
}

    @Bean
    @Profile("!dev")
    fun getResourcesPathProvider() : StaticResourcesPathProvider {
        return object : StaticResourcesPathProvider {
            override fun GetStaticResourcesPath(): String {
                return "classpath:/static/";
            }
        }
    }
}

接下来,我通过 WebmvcConfigurer 中的 @Autowired 属性使用提供的 bean:

override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
    super.addResourceHandlers(registry)

    var path = staticResourcesPathProvider?.GetStaticResourcesPath()

    registry.addResourceHandler("/static/**")
            .addResourceLocations(path)
}

所以,在开发环境中直接使用文件就可以了。如果您知道如何重新加载 jar,或更友好的解决方案 - 欢迎:)

关于java - JarFileFactory 缓存 jar 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57869023/

相关文章:

java - Spring Boot集成url分页解决方案

java - 使用 Thymeleaf 从 Spring Boot 中的 Jar/war 文件访问 HTML/JavaScript 文件

java - 点击 "send"settext from text field to textarea

java 将对象转换为 double 组

java - 将 application.properties 传递给 Logback 自定义过滤器

java - 具有 Java 配置的 Spring Boot 自定义身份验证提供程序不起作用

java - 如何在 spring-boot 中设置 hibernate.format_sql?

Java WindowBuilder -> 导出为 .jar(可运行或 Applet)

java - 如何在oracle数据库11g中添加sql文件?

javascript - 从 Angular 传递时,Spring Boot 无法识别路径变量数据