Spring MVC 和 Spring Boot 是如何访问静态资源的?
Spring MVC 和 Spring Boot 在配置静态资源访问方面有所不同,Spring Boot 提供了更便捷的自动配置。
一、Spring Boot 如何配置静态资源访问 (推荐方式)
Spring Boot 遵循“约定优于配置”的原则,对静态资源的访问提供了非常方便的自动配置。
-
默认静态资源位置:
Spring Boot 会自动从以下类路径 (classpath) 位置查找静态资源:classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
(常用)classpath:/public/
(常用)
优先级顺序:
META-INF/resources/
>resources/
>static/
>public/
。
这意味着如果你在src/main/resources/static/
目录下放一个style.css
文件,那么你可以通过http://localhost:8080/style.css
来访问它。 -
WebJars 支持:
Spring Boot 也自动支持 WebJars。如果你的项目中引入了 WebJars 依赖(例如 Bootstrap, jQuery),它们会自动从classpath:/META-INF/resources/webjars/
提供服务。
例如,如果引入了bootstrap.jar
,那么它的资源可以通过http://localhost:8080/webjars/bootstrap/{version}/css/bootstrap.css
访问。 -
自定义静态资源位置:
如果你想使用其他位置,可以在application.properties
或application.yml
中配置:# application.properties spring.web.resources.static-locations=classpath:/my-custom-static/,classpath:/another-location/ # 注意:这会覆盖默认位置,如果你还想使用默认位置,需要显式包含它们,例如: # spring.web.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/my-custom-static/
# application.yml spring:web:resources:static-locations:- classpath:/my-custom-static/- classpath:/another-location/# - classpath:/static/ # 如果覆盖了默认,想保留默认的需要加上
-
自定义静态资源访问路径前缀:
默认情况下,静态资源直接从根路径 (/
) 开始访问。你可以修改这个前缀:# application.properties spring.mvc.static-path-pattern=/static-assets/**
# application.yml spring:mvc:static-path-pattern: /static-assets/**
配置后,
src/main/resources/static/style.css
对应的访问路径将变为http://localhost:8080/static-assets/style.css
。 -
缓存控制:
Spring Boot 允许你配置静态资源的缓存策略:# application.properties spring.web.resources.cache.period=3600 # 缓存周期,单位秒。设为0禁用缓存。 spring.web.resources.cache.cachecontrol.max-age=3600 spring.web.resources.cache.cachecontrol.must-revalidate=true # ... 其他 Cache-Control 指令
-
Resource Chain (资源链) - 高级:
Spring Boot 支持资源链,可以用于版本化资源(在文件名中加入hash值以实现缓存清除)等。# application.properties spring.web.resources.chain.enabled=true # 通常默认是true spring.web.resources.chain.strategy.content.enabled=true # 基于内容的版本策略 spring.web.resources.chain.strategy.content.paths=/** spring.web.resources.chain.strategy.fixed.enabled=true # 固定版本策略 spring.web.resources.chain.strategy.fixed.paths=/js/lib/ spring.web.resources.chain.strategy.fixed.version=1.0.0
启用后,你可以在模板(如Thymeleaf)中使用
@{}
语法来获取版本化的URL:<link th:href="@{/css/style.css}" rel="stylesheet">
会被解析为类似/css/style-a2c4e1f.css
的路径。
二、“传统” Spring MVC 如何配置静态资源访问
在不使用Spring Boot自动配置的传统Spring MVC项目中,你需要显式配置静态资源处理器。
-
XML 配置 (
spring-mvc-config.xml
或类似文件):
你需要告诉DispatcherServlet
将特定模式的请求交给默认的 Servlet 处理器或者专门的资源处理器来处理静态资源,而不是尝试寻找 Controller。<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 启用注解驱动的MVC --><mvc:annotation-driven /><!-- 扫描Controller --><context:component-scan base-package="com.example.controller" /><!-- 静态资源处理器 --><!-- mapping: 对外暴露的访问路径 --><!-- location: 静态资源在项目中的实际位置 (可以是类路径、文件系统路径或WEB-INF下) --><mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" cache-period="31556926" /><mvc:resources mapping="/static/**" location="classpath:/static/" /><mvc:resources mapping="/images/**" location="file:///opt/myapp/images/" /><!-- 如果你的DispatcherServlet映射的是"/" (拦截所有请求),你需要这个来让容器的默认Servlet处理未被Spring MVC处理的静态资源请求.这对于直接放在webapp根目录下的静态资源有用(不推荐)。 --><mvc:default-servlet-handler /><!-- 视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean> </beans>
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
:mapping
: 当请求URL以/resources/
开头时,例如http://localhost:8080/myapp/resources/css/style.css
。location
: Spring会去webapp/WEB-INF/resources/
目录下查找对应的css/style.css
文件。classpath:/static/
: 表示从类路径下的static
目录查找。
<mvc:default-servlet-handler />
: 如果DispatcherServlet
映射了/
(即处理所有请求),这个配置会允许容器的默认Servlet处理那些没有被Spring MVC Controller或<mvc:resources>
匹配到的请求。这通常用于服务那些直接放在webapp
根目录下的静态文件。
-
Java 配置 (使用
WebMvcConfigurer
):
如果你使用Java配置,你需要创建一个实现WebMvcConfigurer
接口的配置类。import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver;@Configuration @EnableWebMvc // 启用Spring MVC (等同于XML中的 <mvc:annotation-driven />) @ComponentScan(basePackages = "com.example.controller") public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**") // 对外暴露的访问路径.addResourceLocations("/WEB-INF/resources/") // 实际资源位置.setCachePeriod(31556926); // 缓存周期 (秒)registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");registry.addResourceHandler("/images/**").addResourceLocations("file:///opt/myapp/images/"); // 文件系统路径// WebJars 支持 (手动配置)registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}// 配置默认的Servlet来处理静态文件 (等同于XML中的 <mvc:default-servlet-handler />)@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}@Beanpublic InternalResourceViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/jsp/");resolver.setSuffix(".jsp");return resolver;} }
总结:
- Spring Boot: 推荐方式。通过自动配置,你只需要将静态资源放在约定的目录 (
src/main/resources/static
,src/main/resources/public
等) 即可,几乎零配置。自定义也非常简单,通过application.properties/yml
文件即可。 - Spring MVC (传统): 需要显式配置。通过XML (
<mvc:resources>
) 或Java配置 (WebMvcConfigurer
的addResourceHandlers
方法) 来映射URL到静态资源的位置。
对于新项目,强烈建议使用Spring Boot,因为它极大地简化了包括静态资源在内的各种配置。