SpringMVC 配置静态资源映射详解

9 阅读4分钟

SpringMVC 配置静态资源映射详解

本文将详细介绍 SpringMVC 中静态资源映射的配置方法,包括传统 XML 配置和基于 Java 的配置方式,并提供实际应用示例。

一、静态资源映射的基本概念

静态资源映射是将 Web 请求路径映射到实际的静态资源文件位置的过程。在 Web 应用中,CSS、JavaScript、图片等静态资源需要能够被浏览器直接访问,这就需要通过静态资源映射来实现。

二、Spring MVC 传统 XML 配置方式

1. <mvc:resources> 标签配置

在 Spring MVC 的 XML 配置文件中,可以使用 <mvc:resources> 标签来配置静态资源映射:

<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"
       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">

    <!-- 配置静态资源映射 -->
    <mvc:resources mapping="/static/**" location="/static/" />
    
    <!-- 或者映射到 classpath 下的资源 -->
    <mvc:resources mapping="/assets/**" location="classpath:/assets/" />
    
    <!-- 映射到本地文件系统 -->
    <mvc:resources mapping="/files/**" location="file:/path/to/files/" />
    
    <!-- 启用默认的 Servlet 处理器,处理未映射的请求 -->
    <mvc:default-servlet-handler />
    
</beans>

2. 参数说明

  • mapping:指定请求的 URL 模式,** 表示匹配任意子路径
  • location:指定静态资源的实际位置,可以是以下几种形式:
    • 相对路径(相对于 Web 应用根目录)
    • classpath: 前缀,表示从类路径加载
    • file: 前缀,表示从本地文件系统加载

三、Spring MVC Java 配置方式

在使用 Java 配置的 Spring MVC 应用中,可以通过实现 WebMvcConfigurer 接口并重写 addResourceHandlers 方法来配置静态资源映射。

1. 基本配置示例

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 映射 Web 请求路径 /static/** 到 /static/ 目录
        registry.addResourceHandler("/static/**")
                .addResourceLocations("/static/");
                
        // 映射 Web 请求路径 /assets/** 到 classpath:/assets/ 目录
        registry.addResourceHandler("/assets/**")
                .addResourceLocations("classpath:/assets/");
                
        // 映射 Web 请求路径 /files/** 到本地文件系统路径
        registry.addResourceHandler("/files/**")
                .addResourceLocations("file:/path/to/files/");
    }
}

2. 高级配置选项

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static/**")
            .addResourceLocations("/static/")
            .setCachePeriod(3600)  // 设置缓存时间(秒)
            .resourceChain(true);  // 启用资源链
}

四、SpringBoot 默认的静态资源映射规则

SpringBoot 对静态资源映射有默认配置,在 WebMvcAutoConfiguration 类中定义了以下映射规则:

  1. WebJars 资源:请求路径 /webjars/** 映射到 classpath:/META-INF/resources/webjars/

  2. 静态资源文件夹:以下路径的静态资源可以直接访问:

    • /static
    • /public
    • /resources
    • /META-INF/resources
  3. 欢迎页index.html 文件会被自动识别为欢迎页

五、SpringBoot 自定义静态资源映射

在 SpringBoot 项目中,可以通过实现 WebMvcConfigurer 接口来自定义静态资源映射规则。

1. 基本配置示例

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 自定义静态资源映射
        registry.addResourceHandler("/custom/**")
                .addResourceLocations("classpath:/custom/");
    }
}

2. 映射本地文件系统路径

这在文件上传场景中特别有用,可以让上传的文件能够通过 HTTP 直接访问:

package com.example.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("${upload.path}")
    private String uploadPath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 映射上传文件的访问路径
        registry.addResourceHandler("/uploads/**")
                .addResourceLocations("file:" + uploadPath);
    }
}

application.propertiesapplication.yml 中配置上传路径:

# application.yml
upload:
  path: /var/www/uploads/  # Linux 环境
  # path: D:/uploads/  # Windows 环境

六、实际应用示例

1. 图片上传与访问示例

1.1 配置类
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("${upload.path.images}")
    private String imagesUploadPath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 配置图片访问路径
        registry.addResourceHandler("/images/**")
                .addResourceLocations("file:" + imagesUploadPath);
    }
}
1.2 上传控制器
@RestController
@RequestMapping("/api/upload")
public class UploadController {

    @Value("${upload.path.images}")
    private String imagesUploadPath;

    @PostMapping("/image")
    public ResponseEntity<Map<String, String>> uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
        // 确保目录存在
        File directory = new File(imagesUploadPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        
        // 生成唯一文件名
        String filename = UUID.randomUUID().toString() + ".jpg";
        String filePath = imagesUploadPath + filename;
        
        // 保存文件
        file.transferTo(new File(filePath));
        
        // 返回访问URL
        Map<String, String> response = new HashMap<>();
        response.put("url", "/images/" + filename);
        
        return ResponseEntity.ok(response);
    }
}
1.3 配置文件
# application.yml
upload:
  path:
    images: /var/www/images/  # Linux 环境
    # images: D:/images/  # Windows 环境

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

2. 多个静态资源映射配置

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // CSS 和 JavaScript 资源
        registry.addResourceHandler("/css/**", "/js/**")
                .addResourceLocations("classpath:/static/css/", "classpath:/static/js/")
                .setCachePeriod(86400);  // 缓存一天
        
        // 图片资源
        registry.addResourceHandler("/img/**")
                .addResourceLocations("classpath:/static/img/")
                .setCachePeriod(604800);  // 缓存一周
        
        // 上传文件资源
        registry.addResourceHandler("/uploads/**")
                .addResourceLocations("file:/var/www/uploads/");
    }
}

七、注意事项

  1. 路径格式

    • Windows 环境下路径使用 D:/path/to/files/D:\path\to\files\
    • Linux/Unix 环境下路径使用 /path/to/files/
    • 路径末尾的斜杠 / 很重要,不要省略
  2. 文件上传后无法实时访问问题

    • 这是因为文件上传到了物理路径,但没有被复制到编译后的 target 目录
    • 通过配置 file: 前缀的资源映射可以解决这个问题
  3. 缓存配置

    • 对静态资源设置适当的缓存时间可以提高性能
    • 使用 setCachePeriod() 方法设置缓存时间(秒)
  4. WebMvcConfigurer 与 WebMvcConfigurationSupport

    • Spring Boot 2.0 后推荐实现 WebMvcConfigurer 接口而非继承 WebMvcConfigurationSupport
    • 如果同时存在 WebMvcConfigurationSupport 的子类和 WebMvcConfigurer 的实现类,WebMvcConfigurer 可能不会生效
  5. 安全性考虑

    • 生产环境中要注意静态资源的访问权限控制
    • 不要将敏感文件放在可公开访问的静态资源目录下

八、总结

静态资源映射是 Spring MVC 和 Spring Boot 应用中的重要功能,通过本文介绍的方法,您可以灵活地配置各种静态资源的访问路径。无论是映射到 Web 应用内部的静态资源目录,还是映射到外部文件系统,都可以通过简单的配置实现。在实际应用中,根据项目需求选择合适的配置方式,并注意安全性和性能优化。