我们来了解下 SpringBoot 是如何对静态资源进行处理的吧。

【开发环境】:

  • IDEA-2019.1
  • SpringBoot-2.1.1.RELEASE
  • MAVEN-3.5.3

1. SpringBoot 对静态资源映射的处理

SpringBoot 默认为我们提供了静态资源的处理,其通过配置类 WebMvcAutoConfiguration 实现的。此类存放了与 web 开发相关的各种配置属性和方法。

1.1 addResourceHandlers() 方法

查看 WebMvcAutoConfiguration 类的源码。在此类中,addResourceHandlers() 方法对静态资源路径作出了默认的处理

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    } else {
        Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
        CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
        if (!registry.hasMappingForPattern("/webjars/**")) {
            this
	            .customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"})
	            .addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"})
	            .setCachePeriod(this.getSeconds(cachePeriod))
	            .setCacheControl(cacheControl));
        }
        
        // 在此处做静态资源路径映射
		// staticPathPattern 的值为“/**”,下面会做出解释
        String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        if (!registry.hasMappingForPattern(staticPathPattern)) {
            this
            .customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern})
            
 			// this.resourceProperties.getStaticLocations()可以得出静态资源路径
            .addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations()))
            .setCachePeriod(this.getSeconds(cachePeriod))
            .setCacheControl(cacheControl));
        }
    }
}

解释:

staticPathPattern 的值为什么是:/**

this.mvcProperties 是 WebMvcProperties 类型,作为了 WebMvcAutoConfiguration 类的属性。查看WebMvcProperties 类,在其构造方法中,有对 staticPathPattern属性进行初始化,其值为:

public class WebMvcProperties {
	//...
	private String staticPathPattern;
	
	public WebMvcProperties() {
        this.localeResolver = WebMvcProperties.LocaleResolver.ACCEPT_HEADER;
        this.dispatchTraceRequest = false;
        this.dispatchOptionsRequest = true;
        this.ignoreDefaultModelOnRedirect = true;
        this.throwExceptionIfNoHandlerFound = false;
        this.logResolvedException = false;
        this.staticPathPattern = "/**";
        this.async = new WebMvcProperties.Async();
        this.servlet = new WebMvcProperties.Servlet();
        this.view = new WebMvcProperties.View();
        this.contentnegotiation = new WebMvcProperties.Contentnegotiation();
        this.pathmatch = new WebMvcProperties.Pathmatch();
    }
}

this.resourceProperties.getStaticLocations() 得出的静态资源路径是什么?

this.resourceProperties 是 ResourceProperties 类型。查看其源码:

@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", 
    "classpath:/static/", "classpath:/public/"};
    private String[] staticLocations;
    private boolean addMappings;
    private final ResourceProperties.Chain chain;
    private final ResourceProperties.Cache cache;

    public ResourceProperties() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
        this.addMappings = true;
        this.chain = new ResourceProperties.Chain();
        this.cache = new ResourceProperties.Cache();
    }

    public String[] getStaticLocations() {
        return this.staticLocations;
    }
    ...
}

在其构造方法中,将上述四个类路径赋值给了属性 staticLocations

addResourceHandlers() 方法中,可以看出两点关键信息:

1、 访问路径的形式是:/webjars/**,则去 classpath:/META-INF/resources/webjars/ 路径下查找静态资源。

1)、什么是webjars?以jar包的形式引入静态资源文件
2)、webjars的官网

2、访问路径的形式是:/**,则去 classpath:/META-INF/resources/"、"classpath:/resources/"、"classpath:/static/"、"classpath:/public/ 路径下查找静态资源

1.2 如何访问静态资源呢?

例如:访问 static 文件夹下的一张图片
在这里插入图片描述
访问路径:http://localhost:8080/1.jpg千万不要带上static路径,否则,会访问不到

好了,到此,以上都是 SpringBoot 默认为我们提供的静态资源路径映射处理。

问题:

如果我在 resources 路径下新建一个文件 mystatic,然后将 1.jpg 放入其中,那我能访问吗?

http://localhost:8080/1.jpghttp://localhost:8080/mystatic/1.jpg 发现这两个路径访问都是报 404。即:SpringBoot 的默认配置已经不支持了,这时候,需要我们自定义一些配置了。

2. 自定义静态资源映射路径的规则

2.1 通过Java代码的方式

创建一个Java类并实现接口 WebMvcConfigurer,重写 addResourceHandlers() 方法

@Configuration
public class MyStaticConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 访问路径以 “/mystatic” 开头时,会去 “mystatic” 路径下找静态资源
        registry
                .addResourceHandler("/mystatic/**")
                .addResourceLocations("classpath:/mystatic/");
    }

}

main/resources 下新建 mystatic 文件夹,并放入一张图片 1.jpg

访问:http://localhost:8080/mystatic/1.jpg

如果我们将 /mystatic/** 修改为 /**,这时,就是 SpringBoot 默认配置相同,则会覆盖系统的默认配置。可以多次调用 addResourceLocations() 添加目录,优先级先添加的高于后添加的。

【注意】:这样使用代码的方式自定义目录映射,并不影响SpringBoot 的默认映射,可以同时使用。

addResourceLocations("classpath:/mystatic/") 可以指定任何位置:

  • 类路径:classpath:
  • 磁盘文件:file:。如:file:/E:/upload/
2.2 使用配置文件进行配置
2.2.1 只配置静态资源访问路径
spring:
  mvc:
    static-path-pattern: /run/**

再访问静态资源时,需要以“run”开头。如:访问 static/1.jpg 文件。

访问:http:localhost:8080/run/1.jpg

2.2.2 配置静态资源目录
# 配置静态资源访问前缀 默认为“/**”
spring.mvc.static-path-pattern=/test/**
# 配置静态资源路径,默认配置失效。默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 
spring.resources.static-locations=classpath:/mystatic

此种配置会覆盖默认配置,只能以 test 开头来访问 mystatic 文件夹下的静态资源

访问:http://localhost:8080/test/1.jpg

3. SpringBoot 中访问 HTML 页面

两种方式访问html页面:

  • 直接通过路径访问页面(如上)
  • 通过控制器地址跳转至页面

直接通过路径访问页面,这种方式跟上面访问图片一样,就不再说了。下面就简要说一下通过控制器地址跳转到 HTML 页面

步骤一》、先写一个静态页面:在 resources/pages 下新建一个 HTML 页面 hello.html
在这里插入图片描述
步骤二》、写一个控制器 TestController

@Controller
@RequestMapping("/test")
public class TestController {

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

}

步骤三》、配置文件中添加配置

spring:
  mvc:
    view:
      prefix: /pages/  # 前缀 => 页面的位置 /static/pages
      suffix: .html    # 后缀 => 文件的后缀 hello.html

步骤四》、访问

http://localhost:8080/pages/hello.html

===========================================================================================
2023-05-29 更:

映射本地文件,可供前端访问

如:在一个 SpringBoot 工程中如何访问一个 D 盘下的一个图片:D:/zzc/pic/1.jpg

使用配置:

spring:
  mvc:
  	# 资源访问的前缀
    static-path-pattern: /staFile/**
  # 扫描的资源路径
  resources:
    static-locations: classpath:/resources/,classpath:/static/,file:${file.dir}
  
file:
  dir: D:/zzc/pic/

启动,访问:

http://localhost:8092/staFile/1.jpg

使用代码:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Value("${file.dir}")
    private String fileDir;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 访问路径以 “/staFile” 开头时,会去 磁盘 fileDir  路径下找静态资源
        registry
                .addResourceHandler("/staFile/**")
                .addResourceLocations("file:" + fileDir);
    }

}

Spring Boot 2.6+后映射匹配的默认策略已从AntPathMatcher更改为PathPatternParser,需要手动指定为ant-path-matcher

修改 yml 配置

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

配置静态资源路径static-locations、static-path-pattern

【参考资料】:
第4篇:spring boot对静态资源的管理
Spring Boot 静态资源处理
Spring Boot静态资源访问和配置全解析(看不懂你打我)

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐