Spring Boot深度课程系列

峰哥说技术—2020庚子年重磅推出、战胜病毒、我们在行动

10  峰哥说技术:Spring Boot静态资源处理

今天我们聊聊关于 Spring Boot 中关于静态资源的问题,这样,峰哥还是带着大家回顾一下SSM中是怎么处理静资源的。我们得先回到 SSM 环境中,一般来说,我们可以通过 <mvc:resources/> 节点来配置不拦截静态资源,如下所示

<mvc:resources mapping="/js/**" location="/js/"/>

<mvc:resources mapping="/css/**" location="/css/"/>

<mvc:resources mapping="/html/**" location="/html/"/>

由于这是一种Ant风格的路径匹配符, /** 表示可以匹配任意层级的路径,因此上面的代码也可以像下面这样简写:

<mvc:resources mapping="/**" location="/"/>

Spring boot对于Spring MVC的自动化配置都在WebMvcAutoConfiguration,因此对于静态资源的过滤策略我们只要在这里看一下应该就一目了然了。当我们打开改配置类后发现该类有一个静态的内部类WebMvcAutoConfigurationAdapter。

@Configuration(
    proxyBeanMethods = false
)
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
    private final ResourceProperties resourceProperties;
    private final WebMvcProperties mvcProperties;
    private final ListableBeanFactory beanFactory;
    private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
    final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;

public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
        this.resourceProperties = resourceProperties;
        this.mvcProperties = mvcProperties;
        this.beanFactory = beanFactory;
        this.messageConvertersProvider = messageConvertersProvider;
        this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
    }

//其他省略...

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));
        }

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        if (!registry.hasMappingForPattern(staticPathPattern)) {
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }
    }

//其他省略....
}

}

在这里重点考察staticPathPattern和resouruceProperties,这里肯定需要到WebMvcProperties ResourceProperties 去查看。

public class WebMvcProperties {
    private Format messageCodesResolverFormat;
    private Locale locale;
    private WebMvcProperties.LocaleResolver localeResolver;
    private String dateFormat;
    private boolean dispatchTraceRequest;
    private boolean dispatchOptionsRequest;
    private boolean ignoreDefaultModelOnRedirect;
    private boolean publishRequestHandledEvents;
    private boolean throwExceptionIfNoHandlerFound;
    private boolean logResolvedException;
    private String staticPathPattern;
    private final WebMvcProperties.Async async;
    private final WebMvcProperties.Servlet servlet;
    private final WebMvcProperties.View view;
    private final WebMvcProperties.Contentnegotiation contentnegotiation;
    private final WebMvcProperties.Pathmatch pathmatch;

public WebMvcProperties() {
        this.localeResolver = WebMvcProperties.LocaleResolver.ACCEPT_HEADER;
        this.dispatchTraceRequest = false;
        this.dispatchOptionsRequest = true;
        this.ignoreDefaultModelOnRedirect = true;
        this.publishRequestHandledEvents = 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();
    }

//其他省略....

@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;

//其他省略....

}

然后再看标红的地方,在加上WebMvcAutoConfiguration中的SERVLET_LOCATIONS = new String[]{"/"};我们需要的答案就呼之欲出了。最后的结论如下:

Spring Boot 中支持5个静态资源位置,分别是:"classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/",然后在getResourceLocations方法中,又添加了“/”,因此这里返回值一共有5个。其中,/表示webapp目录,即webapp中的静态文件也可以直接访问。静态资源的匹配路径按照定义路径优先级依次降低。我们可以通过一个案例来说明这里的优先级。

案例:分别在静态资源的5个位置放置名称相同但是内容不同的图片,启动后访问,依次删除,验证规则。

步骤:

1)创建Spring boot工程,按下图构建。

特别说明:pom.xml中添加web依赖,除此之外,不需要任何的配置。配置大家已经很熟悉,这里省略。

2)补全工程文件夹,如下图所示。并添加图片到文件夹中。

3)启动项目,任何进行访问。依次删除进行测试。省略过程,大家自己可以试试。

以上所讲的是系统的默认配置,如果我们想自己进行自定义该怎么进行呢?其实也非常简单。有两种方式可以进行,一种是在application.properties中进行配置。另外一种是配置Java类,也可以。下面分别进行举例说明。

1)在application.properties中进行自定义的配置静态资源

spring.resources.static-locations=classpath:/
spring.mvc.static-path-pattern=/**

第一行配置表示定义资源位置,第二行配置表示定义请求 URL 规则。以上文的配置为例,如果我们这样定义了,表示可以将静态资源放在 resources目录下的任意地方,我们访问的时候当然也需要写完整的路径,例如在resources/static目录下有一张名为1.png 的图片,那么访问路径就是 http://localhost:8080/static/1.png ,注意此时的static不能省略。

2)通过Java配置类自定义静态资源

package com.java.chapter02jsp.config;

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

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
 registry.addResourceHandler("/**").addResourceLocations("classpath:/aaa");
    }
}

工程截图如下:

在浏览器中输入:http://localhost:8080/aaa/1.jpg。可以看到图片,这里要说明的是必须带上aaa,否则报错,大家需要特别关注。

很多人用了 Thymeleaf 之后,会将静态资源也放在 resources/templates 目录下,注意,templates 目录并不是静态资源目录,它是一个放页面模板的位置(你看到的 Thymeleaf 模板虽然后缀为 .html,其实并不是静态资源)

峰哥说技术:10-Spring Boot静态资源处理的更多相关文章

  1. 峰哥说技术:09-Spring Boot整合JSP视图

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 09  峰哥说技术:Spring Boot整合JSP视图 一般来说我们很少推荐大家在Spring boot ...

  2. 峰哥说技术:08-Spring Boot整合FreeMarker视图

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 08  峰哥说技术:Spring Boot整合FreeMarker视图 前面带着大家整合了Thymelea ...

  3. 峰哥说技术:04-Spring Boot基本配置

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 04 Spring Boot基本配置 1)容器的相关配置 在Spring Boot中可以内置Tomcat. ...

  4. Spring Boot 静态资源处理

    spring Boot 默认的处理方式就已经足够了,默认情况下Spring Boot 使用WebMvcAutoConfiguration中配置的各种属性. 建议使用Spring Boot 默认处理方式 ...

  5. 从零开始的Spring Boot(3、Spring Boot静态资源和文件上传)

    Spring Boot静态资源和文件上传 写在前面 从零开始的Spring Boot(2.在Spring Boot中整合Servlet.Filter.Listener的方式) https://www. ...

  6. Spring Boot静态资源处理

    Spring Boot静态资源处理 8.8 Spring Boot静态资源处理 当使用Spring Boot来开发一个完整的系统时,我们往往需要用到前端页面,这就不可或缺地需要访问到静态资源,比如图片 ...

  7. Spring Boot 静态资源处理(转)

    Spring Boot 静态资源处理 Spring Boot 系列 Spring Boot 入门 Spring Boot 属性配置和使用 Spring Boot 集成MyBatis Spring Bo ...

  8. 峰哥说技术:03-Spring Boot常用注解解读

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 03 Spring Boot常用注解解读 在Spring Boot中使用了大量的注解,我们下面对一些常用的 ...

  9. 峰哥说技术:01-Spring Boot介绍

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 Spring Boot介绍 A.Spring Boot是什么? 由于Spring是一个轻量级的企业开发框架 ...

随机推荐

  1. scala编程(八)——函数和闭包

    当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段.为了分割控制流,Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数.实际上,Scala 提供了许多 Java 中没有 ...

  2. 推荐几款开源的js日期控件

    做为一个正规的网站,经常需要一些日期或时间的筛选,所以我们今天就推荐二十多款javascript的js日期/时间筛选插件.个个经典,绝对有你需要的. My97DatePicker ,国人开发的一款js ...

  3. [LC] 240. Search a 2D Matrix II

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...

  4. rocket mq 入门文档

    原文地址: http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/ 感谢原作者 十分钟入门RocketMQ 本文首先引出 ...

  5. Serializable 接口(序列化)

    目录 Serializable 接口(序列化) 前言 用途 如何实现 异常 serialVersionUID transient关键字 Serializable 接口(序列化) 前言 查看API文档时 ...

  6. 使用JavaScript获取前一周的日期

    在开发当中遇到了一个关于echarts初始展示当前前7天的数据,正好记录一下如何获取前"n"天的日期, 返回时间格式:2020-02-02 // 返回前number天的日期格式为2 ...

  7. 林轩田机器学习基石笔记3—Types of Learning

    上节课我们主要介绍了解决线性分类问题的一个简单的方法:PLA.PLA能够在平面中选择一条直线将样本数据完全正确分类.而对于线性不可分的情况,可以使用Pocket Algorithm来处理.本节课将主要 ...

  8. 机器学习入门 - 逻辑(Logistic)回归(5)

    原文地址:http://www.bugingcode.com/machine_learning/ex7.html 把所有的问题都转换为程序问题,可以通过程序来就问题进行求解了. 这里的模拟问题来之于C ...

  9. GPU PassThrough in KVM

    实现步骤 环境 OS: # cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) # uname -a Linux hyhive 3 ...

  10. 分布式ID生成策略 · fossi

    分布式环境下如何保证ID的不重复呢?一般我们可能会想到用UUID来实现嘛.但是UUID一般可以获取当前时间的毫秒数再加点随机数,但是在高并发下仍然可能重复.最重要的是,如果我要用这种UUID来生成分表 ...