Spring MVC 和 Spring Boot 是如何访问静态资源的?

Spring MVC 和 Spring Boot 在配置静态资源访问方面有所不同,Spring Boot 提供了更便捷的自动配置。

一、Spring Boot 如何配置静态资源访问 (推荐方式)

Spring Boot 遵循"约定优于配置"的原则,对静态资源的访问提供了非常方便的自动配置。

  1. 默认静态资源位置:

    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 来访问它。

  2. WebJars 支持:

    Spring Boot 也自动支持 WebJars。如果你的项目中引入了 WebJars 依赖(例如 Bootstrap, jQuery),它们会自动从 classpath:/META-INF/resources/webjars/ 提供服务。

    例如,如果引入了 bootstrap.jar,那么它的资源可以通过 http://localhost:8080/webjars/bootstrap/{version}/css/bootstrap.css 访问。

  3. 自定义静态资源位置:

    如果你想使用其他位置,可以在 application.propertiesapplication.yml 中配置:

    properties 复制代码
    # 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/
    yaml 复制代码
    # application.yml
    spring:
      web:
        resources:
          static-locations:
            - classpath:/my-custom-static/
            - classpath:/another-location/
            # - classpath:/static/ # 如果覆盖了默认,想保留默认的需要加上
  4. 自定义静态资源访问路径前缀:

    默认情况下,静态资源直接从根路径 (/) 开始访问。你可以修改这个前缀:

    properties 复制代码
    # application.properties
    spring.mvc.static-path-pattern=/static-assets/**
    yaml 复制代码
    # application.yml
    spring:
      mvc:
        static-path-pattern: /static-assets/**

    配置后,src/main/resources/static/style.css 对应的访问路径将变为 http://localhost:8080/static-assets/style.css

  5. 缓存控制:

    Spring Boot 允许你配置静态资源的缓存策略:

    properties 复制代码
    # 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 指令
  6. Resource Chain (资源链) - 高级:

    Spring Boot 支持资源链,可以用于版本化资源(在文件名中加入hash值以实现缓存清除)等。

    properties 复制代码
    # 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项目中,你需要显式配置静态资源处理器。

  1. XML 配置 (spring-mvc-config.xml 或类似文件):

    你需要告诉 DispatcherServlet 将特定模式的请求交给默认的 Servlet 处理器或者专门的资源处理器来处理静态资源,而不是尝试寻找 Controller。

    xml 复制代码
    <?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/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/mvc
               http://www.springframework.org/schema/mvc/spring-mvc.xsd
               http://www.springframework.org/schema/context
               http://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 根目录下的静态文件。
  2. Java 配置 (使用 WebMvcConfigurer):

    如果你使用Java配置,你需要创建一个实现 WebMvcConfigurer 接口的配置类。

    java 复制代码
    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 {
    
        @Override
        public 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 />)
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    
        @Bean
        public 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配置 (WebMvcConfigureraddResourceHandlers 方法) 来映射URL到静态资源的位置。

对于新项目,强烈建议使用Spring Boot,因为它极大地简化了包括静态资源在内的各种配置。

相关推荐
李昊哲小课2 小时前
Spring Boot SSE 实时推送教程
spring boot·websocket·flux·sseemitter
wno7043 小时前
Spring Boot WebFlux增删改查
java·spring boot·后端
行百里er5 小时前
Spring Insight 里如何把 Span 收成一条链路
spring boot·spring cloud·监控
xcl09255 小时前
24小时自助健身房系统软件开发实战指南:从架构到部署
java·spring boot
ID34610744208 小时前
【课程设计】基于Spring Boot+Vue的游戏账号租赁系统的设计与实现-计算机毕设 附源码50345
javascript·vue.js·spring boot·python·node.js·php·课程设计
宸津-代码粉碎机9 小时前
微服务线上踩坑复盘:接口超时、负载倾斜隐形问题根治方案(生产级配置)
java·大数据·人工智能·python·spring
LuTshoes9 小时前
spring ai 实战RAG(4)-模块化RAG
java·人工智能·spring
wno70410 小时前
Spring Security基础使用
java·后端·spring
小蒜学长10 小时前
基于RFID技术的仓储管理系统设计(代码+数据库+LW)
java·数据库·spring boot·后端·rfid技术·仓储管理
xcl092511 小时前
健身场馆无人自动化系统:从架构设计到落地实践
java·spring boot