Spring MVC 静态资源处理
# Spring MVC 静态资源处理
前言
在 Web 应用中,处理静态资源(如图片、CSS、JavaScript 文件)是基本需求。Spring MVC 提供了默认的静态资源处理机制,同时也允许你根据需求进行自定义配置。
# 1. 默认静态资源处理
Spring MVC 通过配置 DefaultServletHandlerConfigurer
来使用容器的默认 Servlet 处理静态资源请求。这意味着静态资源请求会直接交给容器处理,而不经过 Spring MVC 的控制器。
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 启用默认的 Servlet 来处理静态资源
configurer.enable();
// 如果容器默认的 Servlet 名称不是 "default",可以指定名称
// configurer.enable("myDefaultServlet");
}
2
3
4
5
6
7
8
# 1.1 配置说明
configurer.enable();
:启用默认的 Servlet 处理静态资源请求。当 Spring MVC 没有找到匹配的控制器时,会将请求转发给容器的默认 Servlet(如 Tomcat 的default
Servlet),通常用于处理静态资源。configurer.enable("defaultServletName");
:如果你的容器使用的默认 Servlet 名称不是default
,可以通过此方法指定正确的名称。
# 1.2 默认静态资源目录
Spring Boot 提供了以下默认静态资源目录,资源放在这些目录下时可以通过简单的路径直接访问:
src/main/resources/static
src/main/resources/public
src/main/resources/resources
src/main/resources/META-INF/resources
访问路径示例:假设图片 1.jpg
存放在 src/main/resources/static
目录下,访问路径为 http://localhost:8080/1.jpg
。
# 2. 自定义静态资源路径
在某些情况下,你可能需要将静态资源放在自定义目录中,而不是默认的目录。这时可以通过实现 WebMvcConfigurer
接口并重写 addResourceHandlers
方法来实现。
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 将 /images/** 路径映射到文件系统路径 C:/Users/YourName/Pictures
registry.addResourceHandler("/images/**")
.addResourceLocations("file:/C:/Users/YourName/Pictures/")
.setCachePeriod(3600); // 设置缓存时间为 1 小时
}
}
2
3
4
5
6
7
8
9
10
11
# 2.1 关键配置参数说明
addResourceHandler("/images/**")
:指定对外暴露的 URL 路径模式。当访问路径以/images/
开头时,Spring MVC 会尝试在指定的资源目录中寻找相应的文件。addResourceLocations("file:/C:/Users/YourName/Pictures/")
:指定资源的存放位置。可以是文件系统路径(如file:
前缀)或类路径(如classpath:
前缀)。setCachePeriod(3600)
:设置缓存时间,单位为秒。缓存时间越长,客户端对静态资源的访问性能越好。
什么是 `classpath`?
classpath
是 JVM 用来定位 .class
文件和资源文件(如配置文件、静态资源等)的路径。类路径可以包含以下几种位置:
- 项目的
src/main/resources
目录:Spring Boot 自动将src/main/resources
下的资源文件打包到类路径中。在项目运行时,JVM 会将src/main/resources
中的文件放在类路径中,你可以通过classpath:
前缀轻松访问这些资源。 - 项目编译后的
target/classes
目录:当项目经过编译后,src/main/resources
中的资源会被复制到target/classes
目录。这个目录是类路径中的主要位置,所有在src/main/resources
中的资源都可以通过classpath:
访问。 - 外部依赖的 Jar 包:项目中引用的第三方库(如 Maven 依赖)会被包含在类路径中。Spring Boot 会自动加载这些依赖,确保你的应用可以使用其中的类和资源。
# 2.2 自定义路径的实际应用
如果你需要从磁盘路径 C:/Users/YourName/Pictures/
中提供静态资源,并且在访问时通过 URL /images/**
进行映射,配置如下:
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 配置文件系统路径的静态资源映射
registry.addResourceHandler("/images/**")
.addResourceLocations("file:/C:/Users/YourName/Pictures/")
.setCachePeriod(3600);
}
}
2
3
4
5
6
7
8
9
10
11
在这个配置中:
- 请求 URL 为
http://localhost:8080/images/photo.jpg
会映射到C:/Users/YourName/Pictures/photo.jpg
。 - 如果图片存放在子目录如
C:/Users/YourName/Pictures/gallery/
下,则访问路径为http://localhost:8080/images/gallery/photo.jpg
。
# 2.3 注意事项和最佳实践
做静态资源映射时不建议将资源上传到类路径下。主要原因如下:
类路径通常是只读的:类路径中的资源通常是在应用启动时打包好的,运行时不应进行动态写入或修改。上传文件到类路径中会导致资源管理和更新变得复杂。
资源的动态更新问题:类路径中的资源在应用启动时加载。如果你将文件上传到类路径中,新增或更新的文件无法被动态加载,除非重启应用。这不符合大多数场景下对动态资源管理的需求。
类路径的用途:类路径的设计初衷是用于存放静态资源、配置文件和应用代码,不适合存放用户上传的动态资源。
可维护性和可扩展性:在类路径下存放动态资源会影响应用的可维护性。动态资源通常需要独立的存储路径,方便备份、迁移和访问。如果以后需要将应用扩展到分布式环境或使用云存储,将资源独立存放更为灵活。
推荐的实践
- 将上传文件存放在独立的文件系统路径中,例如
/opt/uploads/
或C:/uploads/
。 - 通过静态资源映射将文件系统路径映射为 URL 路径,方便用户通过浏览器访问上传的文件。
- 使用云存储或数据库存储:对于需要高可用性和扩展性的场景,可以考虑使用云存储(如 AWS S3)或数据库来管理上传的文件。
总之,上传文件的存储路径应与类路径分开,保证类路径的纯净和应用的灵活管理。
# 3. 多资源路径映射
Spring MVC 允许你为一个路径映射多个资源目录,Spring 会按照声明的顺序查找资源。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("classpath:/static/", "file:/C:/Users/YourName/Assets/")
.setCachePeriod(3600);
}
2
3
4
5
6
在这个示例中,/assets/**
路径会先查找类路径下的 static
目录,如果找不到资源再去 C:/Users/YourName/Assets/
中查找。
# 4. 常见问题和注意事项
- 路径优先级:自定义路径优先级高于默认路径,如果自定义路径无法处理请求,Spring 会回退到默认路径。
- 跨域设置:静态资源需要支持跨域访问时,可以通过
addCorsMappings
方法配置跨域策略。 - 安全性考虑:避免将敏感信息(如配置文件、备份文件等)暴露在静态资源目录中。
总结
- 默认处理:Spring Boot 提供了简便的静态资源管理,常用目录如
static
和public
可直接映射。 - 自定义路径:通过
addResourceHandlers
可以自由定义静态资源目录,支持类路径和文件系统路径。 - 缓存策略:可以为静态资源设置缓存,提升客户端访问效率。