我有 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/