Skip to content

静态资源

在响应式栈中查看等效项

此选项提供了一种便捷的方式,可以从基于 Resource 的位置列表中提供静态资源。

在接下来的示例中,给定一个以 /resources 开头的请求,相对路径将用于在 Web 应用程序根目录下的 /public 或类路径下的 /static 中查找并提供静态资源。提供资源时将带有一年的未来过期时间,以确保最大程度地利用浏览器缓存并减少浏览器发出的 HTTP 请求。Last-Modified 信息是从 Resource#lastModified 推导出来的,因此支持带有 "Last-Modified" 标头的 HTTP 条件请求。

以下列表显示了如何执行此操作:

java
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**")
				.addResourceLocations("/public", "classpath:/static/")
				.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)));
	}
}
kotlin
@Configuration
class WebConfiguration : WebMvcConfigurer {

	override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
		registry.addResourceHandler("/resources/**")
			.addResourceLocations("/public", "classpath:/static/")
			.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)))
	}
}
xml
<mvc:resources mapping="/resources/**" location="/public, classpath:/static/"
			   cache-period="31556926" />

另请参阅 静态资源的 HTTP 缓存支持

资源处理程序还支持一系列 ResourceResolver 实现和 ResourceTransformer 实现,您可以使用它们来创建用于处理优化资源的工具链。

您可以使用 VersionResourceResolver 为基于内容计算出的 MD5 哈希、固定的应用程序版本或其他方式的版本化资源 URL。ContentVersionStrategy(MD5 哈希)是一个不错的选择——但有一些明显的例外,例如与模块加载器一起使用的 JavaScript 资源。

以下示例显示了如何使用 VersionResourceResolver

java
@Configuration
public class VersionedConfiguration implements WebMvcConfigurer {

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**")
				.addResourceLocations("/public/")
				.resourceChain(true)
				.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
	}
}
kotlin
@Configuration
class VersionedConfiguration : WebMvcConfigurer {

	override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
		registry.addResourceHandler("/resources/**")
			.addResourceLocations("/public/")
			.resourceChain(true)
			.addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
	}
}
xml
<mvc:resources mapping="/resources/**" location="/public/">
	<mvc:resource-chain resource-cache="true">
		<mvc:resolvers>
			<mvc:version-resolver>
				<mvc:content-version-strategy patterns="/**"/>
			</mvc:version-resolver>
		</mvc:resolvers>
	</mvc:resource-chain>
</mvc:resources>

然后,您可以使用 ResourceUrlProvider 来重写 URL 并应用完整的解析器和转换器链——例如,插入版本。MVC 配置提供了一个 ResourceUrlProvider bean,以便它可以注入到其他 bean 中。对于 Thymeleaf、JSP、FreeMarker 以及其他依赖于 HttpServletResponse#encodeURL 的 URL 标签,您还可以通过 ResourceUrlEncodingFilter 使重写变得透明。

请注意,在同时使用 EncodedResourceResolver(例如,用于提供 gzipped 或 brotli 编码的资源)和 VersionResourceResolver 时,必须按此顺序注册它们。这可以确保始终根据未编码的文件可靠地计算出基于内容的版本。

对于 WebJars,版本化 URL(如 /webjars/jquery/1.2.0/jquery.min.js)是推荐且最高效的使用方式。相关的资源位置在 Spring Boot 中是开箱即用配置好的(或者可以通过 ResourceHandlerRegistry 手动配置),并且不需要添加 org.webjars:webjars-locator-lite 依赖项。

无版本 URL(如 /webjars/jquery/jquery.min.js)通过 WebJarsResourceResolver 提供支持,当类路径中存在 org.webjars:webjars-locator-lite 库时,该解析器会自动注册。该解析器可以重写 URL 以包含 jar 的版本,并且还可以匹配不带版本的传入 URL——例如,从 /webjars/jquery/jquery.min.js 匹配到 /webjars/jquery/1.2.0/jquery.min.js

提示

基于 ResourceHandlerRegistry 的 Java 配置提供了进一步的细粒度控制选项,例如 Last-Modified 行为和优化的资源解析。


补充教学

1. 为什么需要版本化资源?

在生产环境中,浏览器会缓存静态资源(如 CSS/JS)。如果你修改了文件但没改文件名,用户可能看不到更新。通过 VersionResourceResolver,Spring 可以自动在文件名中加入内容哈希(如 style-8c3b.css),当内容改变时哈希也会变,从而强制浏览器下载新版本。

2. 什么是资源链 (Resource Chain)?

资源链允许你对资源进行流水线处理:

  • 解析 (Resolve):找到文件(例如:找 .gz 压缩版,或者根据版本哈希找原文件)。
  • 转换 (Transform):修改内容(例如:在 CSS 文件中替换内部引用的图片路径,带上版本号)。

3. Spring Boot 的默认行为

Spring Boot 默认已经映射了 /static, /public, /resources/META-INF/resources。通常你只需要在 application.properties 中配置 spring.web.resources.chain.strategy.content.enabled=true 就能开启内容版本管理,无需手动写 Java 配置。

Based on Spring Framework.