【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!

本文涉及的产品
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础

1. 文件类型

1.1 Properties

同以前的 properties 用法

1.2 yaml

1.2.1 简介

YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)

非常适合用来做以数据为中序的配置文件。

在 IDEA 中 xxx.yaml 也可以直接写为 xxx.yml

1.2.2 基本语法

  • kay:value;kv 之间有空格
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • “#” 表示注释
  • “与” 表示字符串内容会被 转义/不转义
  • 例如:"zhangsan \n 李四"
  • 双引号不会转义,\n 将作为换行输出
  • 例如:'zhangsan \n 李四'
  • 单引号会转义,\n 将作为字符串输出

1.2.3 数据类型

  • 字面量:单个的、不可再分的值。例如:date、boolean、string、number、null
k: v
  • 对象:键值对的集合。map、hash、set、object
行内写法:k: {k1:v1,k2:v2,k3:v3}
# 或
k:
  k1: v1
  k2: v2
  k3: v3
  • 数组:一组按次序排列的值。array、list、queue
行内写法:k: [v1,v2,v3]
# 或者
k:
  - v1
  - v2
  - v3

1.2.4 示例

person:
    name: zhangsan
    boss: true
    age: 21
    birthdate: 2022/12/9
    interests:
      - 篮球
      - 足球
      - 羽毛球
      - 数字18
    animal: [猫,狗]
    score:
        english: 80
        math: 90
    salarys: [8822,1290]
    pet:
      name: 旺旺
      weight: 99.1
    allpets:
      sick:
        - {name: 小蓝,weight: 92}
        - name: 小红
          weight: 80
        - name: 小黑
          weight: 89
      health: [{name: 小花,weight:90},{name: 小白,weight: 88}]

1.2.5 配置提示

  • 当需要配置提示时,SpringBoot 也有对应的依赖来解决这个问题,我们只需要引入坐标即可。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<!--######################### 插件 ###############################-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!-- 在打包时,防止 SpringBoot 加载过多的类 -->
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-configuration-processor</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

2. SpringMVC 自动配置预览

SpringBoot 的自动配置基于 SpringMVC ,所以大多数场景我们都无需自定义配置

SpringBoot 的自动化配置包括了以下这些默认配置:

  • 内容协商视图解析器和 BeanName 视图解析器
  • 静态资源配置(包括 webjars)
  • 自动化注册 ConverterGenerIcConverterFormatter
  • 支持 HttpMessageConverters
  • 自动注册 MessageCodeResolver(国际化用)
  • 静态 index.html 页支持
  • 自定义每个网站的小图标
  • 自动使用 ConfigurableWebBindingInitializer (DataBinder 负责将请求数据绑定到 JavaBean 上)

如果想要自动化配置,那么 SpringBoot 官方也给出了以下几样建议

  • 不用 @EnableWebMvc 注解。使用 @Configuraion + @WebMvcConfigurer 自定义规则
  • 声明 WebMvcRegistrations 改变默认底层组件
  • 使用 @EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管 SpringMVC

3. 简单功能分析

3.1 静态资源访问

3.1.1 静态资源目录:

只要静态资源放在类路径下/static(or public or /resources or META-INF/resources)

访问:当前项目根路径/ + 静态资源路径

**原理:**静态映射 /**

请求进来,先去找 Controller 看能不能处理。

  • 不能处理的所有请求又都交给静态资源处理器。
  • 当静态资源处理器也无法处理,那么就找到 404

改变默认的静态资源路径:

spring:
  resources:
    static-locations: [ classpath: /haha/]

3.1.2 静态资源访问前缀

默认无前缀

spring:
  mvc:
    static-path-pattern: /res/**

经过设置后,变成了:当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下查找

例子:

  • 没配置前缀前:当前项目根路径/xxx.jpg 即可访问
  • 配置上述前缀后:当前项目根路径/res/xxx.jpg 才能访问

3.1.3 webjar

springboot 支持 webjar;

3.1.3.1 webjar 简略介绍:

‎WebJars 是打包成 JAR(Java Archive)文件的客户端Web库(例如jQuery和Bootstrap)。‎

  • ‎显式轻松地管理基于 JVM 的 Web 应用程序中的客户端依赖项‎
  • ‎使用基于 JVM 的构建工具(例如 Maven、Gradle、sbt 等)下载客户端依赖项‎
  • ‎了解您正在使用的客户端依赖项‎
  • ‎传递依赖项通过 RequireJS 自动解析和选择性加载‎
  • ‎部署在 ‎‎Maven Central 上‎

3.1.3.2 使用:

官网:WebJars - Web Libraries in Jars

直接复制官网中的坐标粘贴至项目的 pom.xml 即可。

<dependency>
    <groupId>org.webjars.npm</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>

如果要访问 webjar 为我们提供的 jar 包,那么访问需要加上前缀 webjar 再访问 webjar 中的插件

示例:/webjars/jquery/3.6.0/dist/jquery.js,后面地址要按照依赖的包路径填写

3.2 欢迎页支持

  • 静态资源路径下生成 index.html
  • 可以配置静态资源路径
  • 但是不可以配置静态资源的访问前缀。否则导致 index.html 不能被默认访问
  • controller 能处理 /index 请求

3.3 自定义 Favicon

跟欢迎页一样,不可以配置静态资源的访问前缀,否则会导致自定义图标失效

**使用:**将 favicon.ico 图标放在静态资源目录下即可。名称不可变

4. 静态资源配置原理

  • SpringBoot 启动默认加载 xxxAutoConfiguration 类(自动配置类)
  • SpringMVC 功能的自动配置类:WebMvcAutoConfiguration,生效
@AutoConfiguration(
    after = {DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
public class WebMvcAutoConfiguration {}
  • 给容器中配置了什么?
@Configuration(
    proxyBeanMethods = false
)
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, WebProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {}
  • 配置文件的相关属性和 xxx 进行了绑定。
  • WebMvcProperties.class=“spring.mvc”
  • WebProperties=“spring.web”

4.1 配置类只有一个有参构造器

  • 有参构造器所有的参数的值都会从容器中绑定
  • 参数说明:
  • WebProperties webProperties:绑定 WebMvcProperties.class=“spring.mvc”
  • WebMvcProperties mvcProperties:绑定 WebProperties=“spring.web”
  • ListableBeanFactory beanFactory:获取 Spring 的 Bean 工厂
  • ObjectProvider<HttpMessageConverters> messageConvertersProvider:找到所有的 HttpMessageConverters
  • ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider:找到 资源处理器的自定义器
  • ObjectProvider<DispatcherServletPath> dispatcherServletPath:调度程序的 Servlet 路径
  • ObjectProvider<ServletRegistrationBean<?>> servletRegistrations:给应用注册 Servlet、Filter
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
    this.resourceProperties = webProperties.getResources();
    this.mvcProperties = mvcProperties;
    this.beanFactory = beanFactory;
    this.messageConvertersProvider = messageConvertersProvider;
    this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
    this.dispatcherServletPath = dispatcherServletPath;
    this.servletRegistrations = servletRegistrations;
    this.mvcProperties.checkConfiguration();
}

4.2 资源处理的默认规则

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    // 获取静态资源的 add-mappings 属性,如果为false,那么所有的静态资源都被禁用了
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    } else {
        // 配置 webjars 的默认路径
        this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
        
        // 配置 静态资源 的访问路径
        this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
            registration.addResourceLocations(this.resourceProperties.getStaticLocations());
            if (this.servletContext != null) {
                ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                registration.addResourceLocations(new Resource[]{resource});
            }
        });
    }
}

我们可以配置 resouce 中的 add-mappings 属性,如果值是 false ,静态资源都将不可访问

spring:
  web:
    resources:
      add-mappings: false

默认 静态资源 的配置路径

public static class Resources {
        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 boolean customized;
        private final WebProperties.Resources.Chain chain;
        private final WebProperties.Resources.Cache cache;
        public Resources() {
            this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
            this.addMappings = true;
            this.customized = false;
            this.chain = new WebProperties.Resources.Chain();
            this.cache = new WebProperties.Resources.Cache();
        }
        public String[] getStaticLocations() {
            // 返回默认路径
            return this.staticLocations;
        }

4.3 欢迎页的处理规则

// HandlerMapping:处理映射,保存了每一个 Handler 能处理哪些请求
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    return welcomePageHandlerMapping;
}
// ###################### 构造器 ######################## 
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
    // 要用欢迎页功能,路径必须是 /**
    if (welcomePage != null && "/**".equals(staticPathPattern)) {
        logger.info("Adding welcome page: " + welcomePage);
        this.setRootViewName("forward:index.html");
    } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
        //调用 Controller /index
        
        logger.info("Adding welcome page template: index");
        this.setRootViewName("index");
    }
}

4.4 favicon(项目图标)

与欢迎页面一样,默认是 /** ,如果没有将会在控制器中找 /favicon.ico 路径

5. ❤️👌SpringBoot 专栏前文回顾

6. 💕👉 其他好文推荐

目录
相关文章
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
490 5
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
166 0
探索Spring Boot的@Conditional注解的上下文配置
|
2月前
|
Java 测试技术 数据安全/隐私保护
通过yaml文件配置自动化测试程序
通过yaml文件可以将自动化测试环境,测试数据和测试行为分开,请看一下案例
91 4
|
JSON Kubernetes API
深入理解Kubernetes配置:编写高效的YAML文件
深入理解Kubernetes配置:编写高效的YAML文件
|
存储 运维 Serverless
函数计算产品使用问题之在YAML文件中配置了环境变量,但在PHP代码中无法读取到这些环境变量,是什么原因
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
266 1
|
Kubernetes 应用服务中间件 nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
260 2
k8s学习--YAML资源清单文件托管服务nginx
|
Kubernetes Docker Perl
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
431 1
ingress相关yaml文件报错且相关资源一切正常解决方法
ingress相关yaml文件报错且相关资源一切正常解决方法
138 0
ingress相关yaml文件报错且相关资源一切正常解决方法
|
运维 Kubernetes Serverless
Serverless 应用引擎使用问题之s.yaml文件中如何使用外部环境变量
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。