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. Python语言学习前提:python安装和pycharm安装

    一.Windows系统python安装 1.python官网:https://www.python.org/downloads/ 2.官网首页:点击Downloads > Windows > ...

  2. 让Spring不再难懂-aop篇

    什么是aop AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP允许 ...

  3. 86)PHP,PDO常用函数

    (1) (2)      举例:假如我的sql语句有问题,那么我输出这两个函数所产生的信息. 还有一组函数: 分别是,开启事务,回滚事务,提交事务,判断是否处于事务中. errorInfo() 错误信 ...

  4. 柱状图dataLabels 文字格式 以及如何获取柱子的name(名称)属性

    dataLabels: { formatter:funnctin(){ return this.percentage //只在堆叠图或饼图中有效,是该点相对总值的百分比. this.point //数 ...

  5. css样式表----------样式属性(背景与前景、边界和边框、列表与方块、格式与布局)

    一.背景与前景 (1).背景 line-height: 1.5 !important;">90; /*背景色(以样式表为主,样式表优先.)*/ background-image:url ...

  6. 第一次作业:使用java实现word count

    github项目地址: https://github.com/changrui520/homework 作业要求: 可执行程序命名为:wc.exe. 该程序处理用户需求的模式为:wc.exe [par ...

  7. 在HADOOP中使用MRUNIT进行单元测试

    在HADOOP中使用MRUNIT进行单元测试 前提 1. 了解JUnit4.x的使用. 2. 了解Mock的概念在单元测试中的应用. 3. 了解Hadoop中MapReduce的编程模型. 如果您对J ...

  8. springboot学习笔记:1.前言

    眼下,随着微服务敏捷开发的势头日益增长,前几年刚刚萌芽的话题,到了现在已经炽手可热.在java圈子里,springboot作为spring生态圈的顶级项目,更是火的不得了.作为java程序员,不了解和 ...

  9. HDU1233 还是畅通工程

    题目: Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连 ...

  10. Python---12函数式编程------12.2返回函数

    返回函数 函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ...