我尝试使用Spring Webflux在我的应用程序上实现静态内容版本控制,如文档中所述:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#webflux-config-static-resources
我使用版本资源解析器使用以下资源处理程序:
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
final VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.addFixedVersionStrategy("test_version", "/**");
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.resourceChain(false)
.addResolver(versionResolver);
}
使用此代码,我希望浏览器在URL中添加“ test_version”后,将所有静态信息存储到类路径中的“ / static /”中。
但是,在请求的所有资源中,只有少数请求是使用URL中的版本完成的。
例如,这是所请求图像的示例:
这是请求的唯一带有URL中添加的版本的图像:
我的JS或CSS资源没有版本化两个。在ETag标头中,我没有看到版本化资源和未版本化资源在HTTP级别(标头等)之间的任何区别。
这是我的项目配置:带有Spring Webflux的Spring Boot 2.1.0.RELEASE,Thymeleaf 3.0.11.RELEASE,Netty服务器。
为什么我的某些资源由VersionResourceResolver处理,而有些则没有?
更新
我在一个示例应用程序上重现了该问题:https://github.com/adsanche/statics-versioning-problem
此应用程序仅包含从Spring Boot 2.1.0.RELEASE开始的Webflux和Thymeleaf。
这是我在application.yml中的版本控制配置:
spring:
resources:
chain:
strategy:
fixed:
enabled: true
version: test_version
请注意,通过模板请求的图像未进行版本控制:
<!-- Can't version this image -->
<img th:src="@{/images/not_versioned.png}">
但是,通过CSS请求的图像版本正确:
.test {
background: url('/images/versioned.png');
}
通过Thymeleaf请求的我的CSS文件也没有版本化:
<head>
<link rel="stylesheet" th:href="@{/css/main.css}"/>
</head>
这与Sring Boot 2.1.1.RELEASE相同。
我在Spring Boot / Thymeleaf配置中缺少某些内容吗?还是有问题?
更新2
我可能对此行为有一些解释。
通过CSS文件调用的资源似乎已被版本化,因为CssLinkResourceTransformer
中有一个getForUriString
调用了ResourceUrlProvider
方法,该方法使用VersionResourceResolver
来解析资源路径。
但是,当从模板中调用SpringWebFluxTemplateEngine
时,似乎可以通过SpringWebFluxLinkBuilder
来解析资源路径,而processLink
的{{1}}方法似乎只是返回了所提供的资源路径,无需转换或调用ResourceUrlProvider
。
我目前发现的唯一解决方法是以这种方式覆盖SpringWebFluxLinkBuilder
并将其设置为SpringWebFluxTemplateEngine
:
@Override
public String processLink(IExpressionContext context, String link) {
return super.processLink(context, "test_version" + link);
}
使用该代码,我可以对模板中调用的所有CSS / JS /图像进行版本控制。但是,我想知道这是否是必要的,或者是否只是缺少一些配置点来自动触发此逻辑。
答案 0 :(得分:1)
首先,您应该删除自定义配置并依赖配置属性,因为您没有做Spring Boot已经实现的任何事情:
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.version=test_version
Spring URL中的资源处理支持在服务器端重写了资源URL。
首先,您应确保已启用它:
@EnableWebMvc
或@EnableWebFlux
,因为它们会禁用Web自动配置<link rel="stylesheet" th:href="@{/static/css/spring.css}">
对于Spring WebFlux,诸如CSS文件之类的资源在提供服务时会被资源处理程序重写。 Spring MVC支持重写到模板引擎中资源的链接,但Spring WebFlux目前不支持。
您可以看到ResourceUrlProvider
契约是异步的,因为它返回了Mono
类型。另一方面,SpringWebFluxLinkBuilder
期望签订阻塞合同。我并不是说Thymeleaf在这里是错的,因为Thymeleaf已经以反应方式渲染了模板。但是,为了呈现这些链接,我们可能需要读取整个资源并计算其哈希值-并且在呈现模板的过程中我们无法做到这一点。
您可以在SPR-15012中了解有关此内容的更多信息,其中介绍了事物的当前状态。随时对此票进行评论-也许事情在此同时发生,或者在Spring Framework / Spring Boot参考文档中可能缺少。