spring-boot - Spring Boot 2.4 应用程序不使用自定义 WebMvcConfigurer#addResourceHandlers 解析静态内容
问题描述
我有一个带有 Spring MVC 的“典型”(接近初始化项目的启动项目)Spring Boot 2.4 应用程序,我想向静态文件添加缓存。为此,我提供了我自己的@Configuration
实现WebMvcConfigurer
. 但是无论我尝试什么,一旦我使用自己的配置,我总是会收到静态资源的 404 错误。
我的静态内容目录结构
src/main/resources/
|- static/
|- res/
|- css/
|- js/
|- images/
|- favicon.ico
问题/问题
我认为我的误解在于如何ResourceHandlerRegistry#addResourceHandler
一起ResourceHandlerRegistry#addResourceLocations
工作。
我尝试以类似于默认资源解析(请参阅 参考资料org.springframework.boot.autoconfigure.web.WebProperties.Resources.CLASSPATH_RESOURCE_LOCATIONS
)的方式执行此操作,并最终得到以下(不工作)代码:
@Configuration
public class CacheStaticResourcesConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/favicon.ico", "/res/**", "/images/**")
.addResourceLocations("classpath:/static")
.setCacheControl(CacheControl.maxAge(7, TimeUnit.DAYS)
.noTransform()
.mustRevalidate());
}
}
解决方案
资源/类路径的解析确实令人困惑,我也花了一些时间来支持它。以下带有大量评论的示例有望阐明一切。
TL;博士:
registry
// Request URLs
.addResourceHandler("/**" /*, ... */)
// Path inside application (refers to src/main/resources directory)
// TRAILING SLASH IS IMPORTANT
.addResourceLocations("classpath:/static/")
Spring 将路径的可变部分从放入的模式附加addResourceHandler()
到.addResourceLocations()
. 例子:
// TRAILING SLASH IS IMPORTANT!
.addResourceLocations("classpath:/static/")
=>
addResourceHandler("/**")
=> GET /res/css/main.css
=> resolved as: "classpath:/static/res/css/main.css"
BUT
addResourceHandler("/res/**")
=> GET /res/css/main.css
(spring only appends the ** to the value from
addResourceLocations())
=> resolved as: "classpath:/static/css/main.css"
工作示例配置
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.concurrent.TimeUnit;
@Configuration
public class CacheStaticResourcesConfiguration implements WebMvcConfigurer {
/**
* We provide a custom configuration which resolves URL-Requests to static files in the
* classpath (src/main/resources directory).
*
* This overloads a default configuration retrieved at least partly from
* {@link WebProperties.Resources#getStaticLocations()}.
*
* @param registry ResourceHandlerRegistry
*/
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
/*
* BE AWARE HERE:
*
* .addResourceHandler(): URL Paths
* .addResourceLocations(): Paths in Classpath to look for file
* root "/" refers to src/main/resources
* For configuration example, see:
* org.springframework.boot.autoconfigure.web.WebProperties.Resources().getStaticLocations()
*
* .addResourceLocations("classpath:/static/")
* =>
* addResourceHandler("/**")
* => GET /res/css/main.css
* => resolved as: "classpath:/static/res/css/main.css"
* BUT
* addResourceHandler("/res/**")
* => GET /res/css/main.css
* (spring only appends the ** to the value from
* addResourceLocations())
* => resolved as: "classpath:/static/css/main.css"
*/
registry
.addResourceHandler("/favicon.ico")
// trailing slash is important!
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS)
.noTransform()
.mustRevalidate());
registry
.addResourceHandler("/res/**")
// trailing slash is important!
.addResourceLocations("classpath:/static/res/")
.setCacheControl(CacheControl.maxAge(7, TimeUnit.DAYS)
.noTransform()
.mustRevalidate());
registry
.addResourceHandler("/images/**")
// trailing slash is important!
.addResourceLocations("classpath:/static/images/")
.setCacheControl(CacheControl.maxAge(7, TimeUnit.DAYS)
.noTransform()
.mustRevalidate());
}
}
推荐阅读
- python - 仅使用单核的多处理
- reactjs - TypeError:tours.map 不是函数。无法对未安装的组件执行 React 状态更新
- javascript - 查找是否存在与指定条件不匹配的子数组
- python - 如何在树莓派 4 上连接 mpr121
- taxii - 通过 cabby 将 STIX 数据推送到 MISP 实例中
- python - 有没有办法将 csv 数据加载到雪花表中并报告每条记录是否已成功加载?(使用 Python)
- reactjs - 反应 | 添加滚动事件监听器(水平)
- node.js - 如何在 Nodejs 中使用 Recaptcha 进行 Ajax 发布请求
- sql - Postgres,在 json_agg 中使用不同的 json_build_object 字段
- xaml - XAML 链绑定不会自动更新