Spring MVC 处理静态资源请求 - ResourceHandler

文章目录

  • [Spring MVC 处理静态资源请求 - ResourceHandler](#Spring MVC 处理静态资源请求 - ResourceHandler)

Spring MVC 处理静态资源请求 - ResourceHandler

一、Spring MVC 处理静态资源的背景和机制

  • 在 Web 应用中,除了动态内容(如通过 Controller 处理的请求返回的视图)外,还包含大量的静态资源,如 HTML 文件、CSS 文件、JavaScript 文件、图片等。
  • Spring MVC 默认不会处理静态资源请求,因为它主要是为处理动态请求设计的。如果直接使用 Spring MVC 的默认配置来处理静态资源,会因为找不到对应的 Controller 处理方法而报 404 错误。
  • Spring MVC 提供了多种方式来处理静态资源。一种常见的方式是通过配置资源处理器(ResourceHandler),它可以将特定路径的请求映射到服务器上的物理资源目录。

二、配置静态资源处理器的方法

有两种主要方式配置静态资源处理器:

1、Java 配置方式(推荐)

通过继承 WebMvcConfigurerAdapter(Spring 4.x) 或实现 WebMvcConfigurer(Spring 5.x+) ,重写 addResourceHandlers 方法。

方式一:继承 WebMvcConfigurerAdapter(Spring 4.x)

java 复制代码
// 导入Spring框架相关的包
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * WebMvcConfig类用于配置Spring MVC的相关设置,特别是静态资源的处理
 * 该类通过继承WebMvcConfigurerAdapter并使用@Configuration注解成为一个配置类
 */
@Configuration  // 表明这是一个配置类,相当于一个XML配置文件
@EnableWebMvc   // 启用Spring MVC的高级配置特性
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    /**
     * 重写addResourceHandlers方法,配置静态资源的处理
     * @param registry 资源处理器注册器,用于注册资源处理的规则
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 添加一个资源处理器
        // addResourceHandler("/static/**") 表示所有以/static/开头的请求路径都会被这个处理器处理
        // addResourceLocations("classpath:/static/") 表示这些静态资源实际存放在类路径下的static目录中
        // 例如,请求路径为/static/js/main.js的资源会从classpath:/static/js/main.js加载
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
		
		// 可添加多个映射规则
        registry.addResourceHandler("/images/**").addResourceLocations("file:/path/to/images/"); // 从文件系统加载

        // 调用父类的方法,确保其他默认的资源处理规则仍然生效
        super.addResourceHandlers(registry);
    }
}

方式二:实现 WebMvcConfigurer(Spring 5.x+)

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 映射 /static/** 路径到类路径下的 static 目录
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
                
        // 可添加多个映射规则
        registry.addResourceHandler("/images/**")
                .addResourceLocations("file:/path/to/images/"); // 从文件系统加载
    }
}

ResourceHandlerRegistry 如何获取到?

在上面的两个示例中,我们会看到重写 addResourceHandlers 方法的入参是:ResourceHandlerRegistry,这个参数又是如何获取到的呢?

其实,在 Spring 框架中,ResourceHandlerRegistry 参数是由 Spring 容器在运行时自动创建并传递给配置方法的。这一过程基于 Spring 的依赖注入机制和配置类处理流程,具体如下:
(1)Spring 容器的初始化流程

当应用启动时,Spring 会:

  1. 扫描配置类 :通过 @Configuration 注解发现WebMvcConfig类。
  2. 创建配置类实例:将WebMvcConfig作为 Spring Bean 管理。
  3. 处理配置方法:调用被@Override标记的配置方法(如 addResourceHandlers)。

(2)参数注入机制

当 Spring 调用 addResourceHandlers(ResourceHandlerRegistry registry) 方法时:

  • 自动创建 Registry 对象:Spring 会创建一个ResourceHandlerRegistry实例,用于收集和注册资源处理器规则。
  • 注入到方法参数:将这个实例作为参数传递给 addResourceHandlers 方法。
  • 方法内部配置:你在方法中调用registry.addResourceHandler(...)时,实际上是在修改这个由 Spring 管理的ResourceHandlerRegistry对象的内部状态。

(3)幕后原理

这一过程依赖于 Spring 的工厂模式和构建器模式:

  • ResourceHandlerRegistry是一个构建器,用于收集资源映射规则。
  • Spring 通过工厂创建这个构建器,并在配置类中提供给你使用。
  • 当配置方法执行完毕后,Spring 会根据ResourceHandlerRegistry中收集的规则,生成实际的HandlerMapping(处理静态资源请求的组件)。

(4)代码示例理解

以下是一个简化的示例,展示 Spring 可能如何内部处理这个过程(实际实现更复杂):

java 复制代码
// 伪代码,展示Spring内部处理流程
public class SpringApplication {
    public void run() {
        // 1. 创建配置类实例
        WebMvcConfig config = new WebMvcConfig();
        
        // 2. 创建ResourceHandlerRegistry
        ResourceHandlerRegistry registry = new ResourceHandlerRegistry();
        
        // 3. 调用配置方法,注入registry
        config.addResourceHandlers(registry);
        
        // 4. 使用registry中收集的规则,创建HandlerMapping
        HandlerMapping resourceHandlerMapping = registry.buildHandlerMapping();
        
        // 5. 将HandlerMapping注册到Spring MVC的处理器链中
        registerHandlerMapping(resourceHandlerMapping);
    }
}

2、XML 配置方式

在spring-mvc.xml中配置:

xml 复制代码
<mvc:resources mapping="/static/**" location="classpath:/static/"/>
<mvc:resources mapping="/images/**" location="file:/path/to/images/"/>

三、静态资源的存放位置

当使用 addResourceLocations 方法时,可以指定多个资源位置,这些位置可以是类路径下的目录(使用 "classpath:" 前缀),也可以是服务器文件系统的绝对路径(如 "file:/path/to/resource/")。例如,addResourceLocations("classpath:/static/","file:/opt/static/"),这样当请求 "/static/style.css" 时,会先在类路径下的 "static" 目录查找,如果找不到,再在 "/opt/static/" 目录查找。

静态资源通常存放在以下位置:

  • 类路径下的static目录(默认位置):src/main/resources/static
  • 类路径下的public目录:src/main/resources/public
  • 类路径下的resources目录:src/main/resources/resources
  • 类路径下的META-INF/resources目录:src/main/resources/META-INF/resources

Spring MVC 会按上述顺序查找资源,直到找到为止。

相关推荐
电商数据girl3 小时前
【经验分享】浅谈京东商品SKU接口的技术实现原理
java·开发语言·前端·数据库·经验分享·eclipse·json
小猫咪怎么会有坏心思呢4 小时前
华为OD机考-货币单位换算-字符串(JAVA 2025B卷)
java·开发语言·华为od
一坨阿亮4 小时前
MyBatis原理
java·开发语言·mybatis
不太可爱的叶某人5 小时前
【学习笔记】深入理解Java虚拟机学习笔记——第7章 虚拟机类加载机制
java·笔记·学习
我的炸串拌饼店5 小时前
ASP.NET MVC 中SignalR实现实时进度通信的深度解析
后端·asp.net·mvc
晴空月明6 小时前
Java 集合框架底层数据结构实现深度解析
java
louisgeek6 小时前
Java Creational 创建型模式之 Builder 建造者模式
java
挑战者6668886 小时前
springboot入门之路(一)
java·spring boot·后端
重整旗鼓~7 小时前
7.索引库操作
java·开发语言