Spring Boot 中的静态资源配置

Spring Boot 对静态资源提供了支持。默认情况下,以下目录为默认的静态资源目录。其中的静态资源可以被直接访问:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/
  • ${user.dir}/public/ (程序运行目录下的 public 目录)

优先级从上往下,当多个静态资源目录中出现同名文件时,越靠上的目录权重越高。

静态资源的处理类是 ResourceHttpRequestHandler,它会正确地处理资源的 Last-Modified 响应和 Range 请求。

静态资源和 RequestMapping 冲突

如果静态资源路径和 @RequestMapping 路径冲突,则 @RequestMapping 优先。

例如,有如下 Controller:

@RestController
@RequestMapping
public class DemoController {

    @GetMapping("/foo")
    public ResponseEntity<String> foo () {
        // 返回字符串 “controller”
        return ResponseEntity.ok("controller");
    }
}

src/main/resources/public 目录下有一个名为 foo 的文本文件,内容如下:

public

启动应用,访问 http://localhost:8080/foo

$ curl http://localhost:8080/foo
controller

你可以看到,响应的内容是 controller,说明 controller 的 @RequestMapping 优先。

另外,对于这种没有后缀、未知类型的静态资源,Spring Boot 会以 “下载” 的形式响应给客户端(添加了 Content-Disposition 响应头)。

默认主页

静态资源根目录中的 index.html 会被当做应用默认的主页。得益于此,创建 Spring Boot 应用后不需要创建 Controller,就可以快速地开发一个应用主页。

src/main/resources/public 目录下创建 index.html,内容如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        index.html
    </body>
</html>

启动应用,访问主页:

$ curl http://localhost:8080
<!DOCTYPE html>
<html>
        <head>
                <meta charset="UTF-8">
                <title>主页</title>
        </head>
        <body>
                index.html
        </body>
</html>

自定义静态资源目录

有两种方式自定义静态资源目录,配置文件和配置类。

在配置文件中配置静态资源目录

你可以在 properties 或者 yaml 中配置静态资源的访问路径和目录。

# 静态资源的访问路径
spring.mvc.static-path-pattern=/**
# 静态资源的目录
spring.web.resources.static-locations[0]=classpath:/public/

spring.mvc.static-path-pattern 指定了静态资源的访问路径,默认为 /**,也就是没有前缀。你可以专门为静态资源配置一个访问路径,如:spring.mvc.static-path-pattern=/static/**

spring.web.resources.static-location 配置用于指定静态资源的目录,它是一个数组,可以配置多个路径。默认值为:[classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/]

静态资源目录不仅可以是 classpath 下的目录,也可以是本地磁盘目录,使用 file: 前缀进行配置,如:

spring.web.resources.static-locations[0]=file:D:\\upload\\

还可以配合 ${} 语法,从环境变量、系统属性中读取目录信息,例如,设置应用启动目录下的 public 目录为静态资源目录:

# ${user.dir} 的值也就是 System.getProperty("user.dir")
spring.web.resources.static-locations[0]=file:${user.dir}\\upload\\

通过 WebMvcConfigurer 配置静态资源目录

通过 WebMvcConfigurer 配置接口的 addResourceHandlers 方法,可以编程式地配置静态资源访问路径和静态资源目录。

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 WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 静态资源访问路径
        registry.addResourceHandler("/**")
                // classpath下的静态资源目录
                .addResourceLocations("classpath:/public/")
                // 本地磁盘下的静态资源目录
                .addResourceLocations("file:D:\\upload\\")
                ;
    }
}

这种方式不支持使用 ${} 表达式。