在我们做Web开发时,免不了与静态资源(css,js,images)打交道,通常的做法是在请求的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);
}
...
}
在SpringBoot中就可以用如下配置
spring:
resources:
chain:
enabled: true
cache: true
version:
content:
enabled: true
paths: /static/**
fixed:
enabled: true
version: 1.0
paths: /js/**,/foo/**
或者
spring:
resources:
chain:
enabled: true
cache: true
version.content:
enabled: true
paths: /static/**
version.fixed:
enabled: true
version: 1.0
paths: /js/**,/foo/**
静态资源路径请根据实际路径修改
**ContentVersionStrategy**MD5策略,如,请求
/javascript/test-69ea0cf3b5941340f06ea65583193168.js
则被解析为:
/javascript/test.js
FixedVersionStrategy固定版本策略,如
/v1.2.3/javascript/test.js
使用ResourceUrlProvider生成包含MD5信息
With a ResourceUrlProvider a resource URL (e.g. /javascript/test.js) can be converted to a versioned URL (e.g. /javascript/test-69ea0cf3b5941340f06ea65583193168.js). A ResourceUrlProvider bean with the id mvcResourceUrlProvider is automatically declared with the MVC configuration.
如果你使用Thymeleaf模板引擎(可以直接访问ResourceUrlProvider Bean),那么前端页面你可以直接这么使用:
<script type="application/javascript"
th:src="${@mvcResourceUrlProvider.getForLookupPath('/javascript/test.js')}">
script>
如果你使用其他例如FreeMarker等模板引擎,你可以通过@ControllerAdvice将ResourceUrlProvider Bean添加到Model Attribute中,就像这么使用:
@ControllerAdvice
public class ResourceUrlAdvice {
@Inject
ResourceUrlProvider resourceUrlProvider;
@ModelAttribute("urls")
public ResourceUrlProvider urls() {
return this.resourceUrlProvider;
}
}
在这种情况下,前端页面可以这么写
<script type="application/javascript"
th:src="${urls.getForLookupPath('/javascript/test.js')}">
script>
这种方式支持所有的模板引擎。
另一种方式是通过ResourceUrlEncodingFilter,其是Servlet Filter,通过重写HttpServletResponse.encodeURL()来生成版本化的资源地址。使用起来也很简单,配置项中增加ResourceUrlEncodingFilter Bean,如下:
@SpringBootApplication
public class MvcApplication extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// same as before ..
}
@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
...
}
如果你正在使用的模板引擎(如:JSPs, Thymeleaf, FreeMarker and Velocity)支持直接调用response.encodeURL()方法,那么版本信息将自动被添加到资源URL中。
例如,在Thymeleaf中,我们可以用@{..} 语法
<script type="application/javascript" th:src="@{/javascript/test.js}">script>
那么最终页面将会如下:
<script type="application/javascript"
src="/javascript/test-69ea0cf3b5941340f06ea65583193168.js">
script>
SpringBoot 1.3.0版本之后,使用* ResourceUrlEncodingFilter*将更加简单
As of Spring Boot 1.3.0, this is now even easier. The Resource chain can be configured via Boot properties and the ResourceUrlEncodingFilter is automatically registered
Links to resources are rewritten at runtime in template, thanks to a ResourceUrlEncodingFilter, auto-configured for Thymeleaf and Velocity. You should manually declare this filter when using JSPs. Other template engines aren’t automatically supported right now, but can be with custom template macros/helpers and the use of the ResourceUrlProvider.
https://github.com/spring-projects/spring-boot/pull/3123
https://dzone.com/articles/2-step-resource-versioning-with-spring-mvc