提供静态资源时,通常的做法是将某种版本信息附加到资源URL。 这使浏览器可以无限期地缓存资源。 每当资源的内容更改时,URL中的版本信息也会更改。 更新的URL会强制客户端浏览器放弃缓存的资源,并从服务器重新加载最新的资源版本。
使用Spring,只需两个简单的步骤即可配置版本化的资源URL。 在这篇文章中,我们将看到它是如何工作的。
提供版本化网址
首先,我们需要告诉Spring应该通过版本化的URL访问资源。 这是在资源处理程序MVC配置中完成的:
@Configuration
public class MvcApplication extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
VersionResourceResolver versionResourceResolver = new VersionResourceResolver()
.addVersionStrategy(new ContentVersionStrategy(), "/**");
registry.addResourceHandler("/javascript/*.js")
.addResourceLocations("classpath:/static/")
.setCachePeriod(60 * 60 * 24 * 365) /* one year */
.resourceChain(true)
.addResolver(versionResourceResolver);
}
...
}
在这里,我们为位于类路径内名为static的文件夹中JavaScript文件创建资源处理程序。 这些JavaScript文件的缓存时间设置为一年。 重要的部分是VersionResourceResolver ,它支持带有版本信息的资源URL。 VersionStrategy用于获取资源的实际版本。
在此示例中,我们使用ContentVersionStrategy 。 此VersionStrategy实现从资源的内容计算MD5哈希并将其附加到文件名。
例如:假设我们在classpath:/ static /目录中有一个JavaScript文件test.js。 test.js的MD5哈希为69ea0cf3b5941340f06ea65583193168。
现在,我们可以将请求发送至:
/javascript/test-69ea0cf3b5941340f06ea65583193168.js
它将解析为classpath:/static/test.js。
请注意,仍然可以在没有MD5哈希的情况下请求资源。 因此,此请求也适用:
/javascript/test.js
另一个VersionStrategy实现是FixedVersionStrategy 。 FixedVersionStrategy使用固定版本字符串作为前缀添加到资源路径。
例如:
/v1.2.3/javascript/test.js
生成版本化的URL
现在,我们需要确保应用程序生成的资源URL包含MD5哈希。
一种解决方法是使用ResourceUrlProvider 。 使用ResourceUrlProvider,可以将资源URL(例如/javascript/test.js)转换为版本化的URL(例如/javascript/test-69ea0cf3b5941340f06ea65583193168.js)。 使用MVC配置会自动声明ID为mvcResourceUrlProvider的ResourceUrlProvider bean。
如果您将Thymeleaf用作模板引擎,则可以使用@bean语法直接从模板访问ResourceUrlProvider bean。
例如:
<script type="application/javascript"
th:src="${@mvcResourceUrlProvider.getForLookupPath('/javascript/test.js')}">
</script>
如果使用的模板引擎不能直接访问Spring Bean,则可以将ResourceUrlProvider Bean添加到模型属性中。 使用ControllerAdvice ,可能看起来像这样:
@ControllerAdvice
public class ResourceUrlAdvice {
@Inject
ResourceUrlProvider resourceUrlProvider;
@ModelAttribute("urls")
public ResourceUrlProvider urls() {
return this.resourceUrlProvider;
}
}
然后,在视图内部,我们可以使用urls模型属性访问ResourceUrlProvider:
<script type="application/javascript"
th:src="${urls.getForLookupPath('/javascript/test.js')}">
</script>
此方法应与所有支持方法调用的模板引擎一起使用。
生成版本化URL的另一种方法是使用ResourceUrlEncodingFilter 。 这是一个Servlet筛选器,它重写HttpServletResponse.encodeURL()方法以生成版本化的资源URL。
要使用ResourceUrlEncodingFilter,我们只需要向配置类中添加一个额外的bean:
@SpringBootApplication
public class MvcApplication extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// same as before ..
}
@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
...
}
如果您使用的模板引擎调用了响应encodeURL()方法,则版本信息将自动添加到URL。 这将适用于JSP,Thymeleaf,FreeMarker和Velocity。
例如:通过Thymeleaf,我们可以使用标准的@ {..}语法来创建URL:
<script type="application/javascript" th:src="@{/javascript/test.js}"></script>
这将导致:
<script type="application/javascript"
src="/javascript/test-69ea0cf3b5941340f06ea65583193168.js">
</script>
摘要
将版本信息添加到资源URL是最大化浏览器缓存的常见做法。 使用Spring,我们只需要定义一个VersionResourceResolver和一个VersionStrategy即可提供版本化的URL。 在模板引擎内部生成版本化URL的最简单方法是使用ResourceUrlEncodingFilter。
如果标准的VersionStrategy实现不符合您的要求,则可以创建我们自己的VersionStrategy实现。
- 您可以在GitHub上找到完整的示例源代码。
翻译自: https://www.javacodegeeks.com/2015/09/resource-versioning-with-spring-mvc.html