一、ResourceHandlerRegistry简介
ResourceHandlerRegistry是Spring MVC框架中用于配置静态资源处理的重要组件,在Spring Boot项目中同样适用。它允许开发者自定义静态资源(如CSS、JavaScript、图片、字体等)的访问路径映射,解决静态资源被DispatcherServlet拦截导致404的问题。
二、Spring Boot中的静态资源处理机制
在Spring Boot中,默认已经配置了一些静态资源位置,包括:
classpath:/static/classpath:/public/classpath:/resources/classpath:/META-INF/resources/
以及文件系统中的:
/(项目根目录)
但是,当我们需要自定义静态资源位置或路径时,就需要使用ResourceHandlerRegistry进行配置。
三、ResourceHandlerRegistry的基本使用
1. 创建配置类
在Spring Boot项目中,创建一个配置类实现WebMvcConfigurer接口:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 静态资源配置将在这里添加
}
}
2. 基本配置示例
示例1:映射classpath下的静态资源
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
这样配置后,前端可以通过/static/路径访问src/main/resources/static/目录下的资源。
示例2:映射多个静态资源位置
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations(
"classpath:/static/",
"classpath:/custom-static/",
"file:/opt/app/static/" // 文件系统中的路径
);
}
Spring会按照添加顺序依次查找资源,先在classpath:/static/中查找,找不到再到classpath:/custom-static/中查找,最后到文件系统中的/opt/app/static/目录查找。
示例3:映射文件系统中的静态资源
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:/var/www/uploads/");
}
这样配置后,前端可以通过/uploads/路径访问服务器文件系统中/var/www/uploads/目录下的资源。
四、高级配置
1. 缓存控制
通过setCacheControl方法可以设置更精细的缓存策略:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)
.cachePublic()
.immutable());
}
或者使用较旧的setCachePeriod方法(单位:秒):
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(31536000); // 缓存1年(365 * 24 * 60 * 60秒)
}
2. 版本化资源(缓存破坏)
为了实现缓存破坏(当资源更新时客户端能获取新版本),可以使用资源处理器:
@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
然后在HTML中使用Thymeleaf或Spring标签库引用资源时,可以自动添加版本号:
<!-- 使用Thymeleaf -->
<link th:href="@{/static/css/style.css}" rel="stylesheet"/>
<!-- 或使用Spring标签库 -->
<link href="${pageContext.request.contextPath}/static/css/style.css" rel="stylesheet"/>
3. 优先级控制
当配置多个资源位置时,Spring会按照addResourceLocations中指定的顺序查找资源。第一个找到的资源将被返回。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations(
"classpath:/override-static/", // 优先查找
"classpath:/default-static/", // 其次查找
"file:/external/static/" // 最后查找
);
}
五、Spring Boot特定配置
1. 覆盖默认静态资源位置
如果需要改变Spring Boot默认的静态资源处理方式,可以完全自定义:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 先清除默认配置(不推荐,除非必要)
// registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
// 自定义配置
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/custom-static/");
}
2. 与默认配置共存
通常更好的做法是与默认配置共存,只添加自定义配置:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 添加自定义静态资源位置,不影响默认配置
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:/var/www/uploads/");
// 如果需要添加额外的静态资源位置
registry.addResourceHandler("/assets/**")
.addResourceLocations("classpath:/assets/");
}
}
3. 使用application.properties/yml配置
对于简单的静态资源配置,也可以直接在application.properties或application.yml中配置:
# application.properties
spring.web.resources.static-locations=classpath:/static/,classpath:/custom-static/,file:/opt/app/static/
spring.web.resources.cache.period=31536000
spring.web.resources.cache.cachecontrol.max-age=365d
spring.web.resources.cache.cachecontrol.public=true
或者YAML格式:
# application.yml
spring:
web:
resources:
static-locations:
- "classpath:/static/"
- "classpath:/custom-static/"
- "file:/opt/app/static/"
cache:
period: 31536000
cachecontrol:
max-age: 365d
public: true
六、常见问题及解决方案
1. 静态资源404错误
可能原因及解决方案:
- 路径配置错误:检查
addResourceHandler和addResourceLocations的路径是否正确 - 资源位置错误:确保资源确实存在于配置的位置
- 缓存问题:开发时禁用缓存或强制刷新浏览器
2. 资源路径冲突
当自定义路径与Controller路径冲突时:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 确保静态资源路径不会与Controller路径冲突
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/static/");
}
// Controller中避免使用相同的路径前缀
@RestController
@RequestMapping("/api") // 使用不同的前缀
public class MyController {
// ...
}
3. 开发与生产环境不同配置
可以使用Spring Profile为不同环境配置不同的静态资源位置:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Value("${static.resource.location}")
private String staticResourceLocation;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations(staticResourceLocation);
}
}
然后在application-dev.properties和application-prod.properties中分别配置:
# application-dev.properties
static.resource.location=classpath:/static/
# application-prod.properties
static.resource.location=file:/opt/app/static/,classpath:/static/
七、最佳实践
- 组织好静态资源目录结构:按类型组织CSS、JS、图片等资源
- 开发环境禁用缓存:便于实时查看资源修改效果
- 生产环境启用长期缓存:提升性能,配合版本控制实现缓存破坏
- 合理规划资源路径:避免与Controller路径冲突
- 考虑CDN部署:对于大型应用,可以将静态资源部署到CDN
通过合理使用ResourceHandlerRegistry,您可以灵活地管理Spring Boot应用中的静态资源,确保它们能够高效、可靠地被客户端访问。

4285

被折叠的 条评论
为什么被折叠?



