【SpringBoot 2学习笔记】《四》配置文件探秘

4.1 配置文件说明

SpringBoot2工程中默认使用全局的配置文件,配置文件名也是固定:application。通过配置文件中配置项的设定,完成SpringBoot2自动配置的默认值的修改,SpringBoot2会在底层自动配置好。配置文件可以有两种形式:yml和properties。实际上,yml文件的配置与properties文件只是简写和缩进方式上面的细微差别,所以本人沿用原来代码风格,统一使用properties文件进行配置。

  • application.properties

  • application.yml

4.2 YAML介绍

YAML是专注于写配置文件的语言,这个名字的含义是YAML Ain’t Markup Language(YAML不是一种标记语言),但是实际上YAML还是一种标记语言,只不过是更加聚焦于数据的标记语言。基本语法规则如下:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格。
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 表示注释,从这个字符一直到行尾,都会被解析器忽略。

4.2.1 YAML基本语法

**k:(空格)v:**表示键值对,注意空格必须有。通过空格的缩进来配置项控制层级关系,左对齐的一列数据属于同一个层次。属性和值也是大小写敏感。

server:
    port: 8081

4.2.2 YAML值的写法

4.2.2.1、字面量即普通的值(数字,字符串,布尔)

​ k: v:直接按照字面来写,其中字符串默认不用加上单引号或者双引号。

“”:双引号;特殊字符会作为本身想表示的意思,不会进行转义

name: “Gavin\n LN SY”:输出;Gavin换行 LN SY

‘’:单引号;将对特殊字符进行转义,特殊字符最终只是一个普通的字符串数据

name: ‘Gavin\n LN SY’:输出;Gavin\n LN SY

4.2.2.2 对象(属性和值)、Map(键值对)

k: v:通过在下一行来写对象的属性和值的对应关系,注意缩进方式。对象仍然是K:V的方式,方便阅读。

扫描二维码关注公众号,回复: 8869266 查看本文章
users:
		name: Gavin
		age: 28

同时也支持行内写法:

users: {name: Gavin,age: 18}
4.2.2.3 数组(List、Set)

-值表示数组中的一个元素

animals:
 - cat
 - dog
 - pig
4.2.2.4 复合类型数据
users:
  name: Gavin
  age: 28
  birth: 2017/10/18
  maps:
    school: NEU
    class: 99
  phones:
    ‐ 13909871277
    ‐ 13803451232
  dog:
    name: 二黑
    age: 4

4.3 配置文件内容读取

配置文件(application.properties)

server.servlet.context-path=/gavin
server.port=9001

user.username=gavin
user.password=gavinpw
user.age=28

4.3.1 ConfigurationProperties 进行属性绑定(默认配置文件)

从application.properties中读取前缀为“user”的配置项目信息,给对应的组件(JavaBean)赋值。

JavaBean代码

/**
 * 将配置文件中配置的每一个属性的值,映射到BaseUser组件的元素中
 * 注意:
 * 1. @ConfigurationProperties:通知SpringBoot2将该组件中的所有属性和配置文件指定的配置项进行绑定
 * 2. prefix = "user":配置文件中指定绑定属性的元素前缀
 * 3. @Component:该JavaBean需要声明为容器中的组件,才能使用的@ConfigurationProperties功能
 *
 */
@Component
@ConfigurationProperties(prefix = "user")
public class BaseUser {
    private String username;
    private String password;
    private int age;

POM文件中需要导入配置文件处理器

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</dependency>

在Controller文件中取得对应的属性值并返回

package com.gavinbj.psbigdata.controller;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gavinbj.psbigdata.bean.BaseUser;

@RestController
@RequestMapping("/api")
public class HelloController {
	
    @Resource
    private BaseUser user;

    @GetMapping("/hello")
    public String hello() {
    	
    	System.out.println("使用@ConfigurationProperties读取配置文件结果:" + user.getUsername() + ": " + user.getPassword());
    	
      return "读取配置文件成功";
    
    }
}

启动执行运行结果:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

....... 此处省略启动内容


2019-11-28 21:09:56.195  INFO 5908 --- [nio-9001-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
使用@ConfigurationProperties读取配置文件结果:gavin: gavinpw

4.3.2 ConfigurationProperties 进行属性绑定(指定properties文件)

user.properties

user2.username=你好
user2.password=gavinpw
user2.age=28

JavaBean代码:

/**
 * 将配置文件中配置的每一个属性的值,映射到BaseUser组件的元素中
 * 注意:
 * 1. @ConfigurationProperties:通知SpringBoot2将该组件中的所有属性和配置文件指定的配置项进行绑定
 * 2. prefix = "user":配置文件中指定绑定属性的元素前缀
 * 3. @Component:该JavaBean需要声明为容器中的组件,才能使用的@ConfigurationProperties功能
 * 4. @PropertySource: 指定外部配置文件的路径,配置项中有中文需要指定 encoding = "utf-8"
 */
@Component
@ConfigurationProperties(prefix = "user2")
@PropertySource(
	value = {"user.properties"},
	encoding = "utf-8"
)
public class BaseUser {
    private String username;
    private String password;
    private int age;

启动执行运行结果:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

....... 此处省略启动内容


2019-11-28 21:09:56.195  INFO 5908 --- [nio-9001-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
使用@ConfigurationProperties读取配置文件结果:你好: gavinpw

4.3.3 完整数据对应示例

配置文件中(meet.properties)直接对应复杂数据类型,例如:List、Map等

# 简单的字符串
meet.name=例会
meet.joins=12

# List类型数据
meet.person[0]=张三
meet.person[1]=李四

# Map类型的数据
meet.detail.task=codereview
meet.detail.location=第二会议室

# 时间类型的数据
meet.date=2019/11/28 13:30:30

对应的JavaBean代码:

// 配置文件前缀为 meet
@ConfigurationProperties(prefix = "meet")
// 获取外部的配置文件文件,需要指定配置文件的路径
@PropertySource(
    ignoreResourceNotFound = true,
    value = "meet.properties",
    encoding = "utf-8"
)
@Component
@Data
public class MeetInfo {
    private String name;
    private int joins;
    private List<String> person;
    private Map<String, String> detail;
    private Date date;
}

启动执行运行结果:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

....... 此处省略启动内容


2019-11-28 21:09:56.195  INFO 5908 --- [nio-9001-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
使用@ConfigurationProperties读取配置文件结果:例会: 第二会议室

4.4 @Value获取值和@ConfigurationProperties获取值比较

@ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

建议:

  • 在某个业务逻辑中需要获取一下配置文件中的某项值,推荐使用@Value

  • 整体的配置文件和专门的JavaBean进行映射,推荐直接使用@ConfigurationProperties

4.5 Profile文件

4.5.1 多Profile文件

在多个环境中的主配置文件编写,文件名可以是:application-{profile}.properties。默认使用application.properties的配置。

4.5.2 yml多文档块配置

server:
  port: 8081
  
spring:
  profiles:
    active: prod  #指定属于哪个环境

---
server:
  port: 8092
spring:
  profiles: dev
  
---
server:
  port: 8093
spring:
  profiles: prod 

4.5.3 激活指定profile方式

  • 通过在配置文件中设定:spring.profiles.active=dev
  • 通过命令行参数方式设定:java -jar psbigdata.jar --spring.profiles.active=dev;
  • 通过设定虚拟机参数,优先级大于配置文件:-Dspring.profiles.active=dev

4.6 配置文件加载位置

SpringBoot项目启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件。

  • –file:./config/
  • –file:./
  • –classpath:/config/
  • –classpath:/

说明:优先级由高到底,高优先级的配置会覆盖低优先级的配置。同时SpringBoot会从这四个位置全部加载主配置文件,并采用并集互补的方式合成配置项的读取。还可以通过spring.config.location来改变默认的配置文件位置。

如果使用命令行参数的形式,启动项目的时候来指定配置文件的新位置优先级大于配置文件,同时命令行参数指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。

其他说明请参考官方文档

4.7 自动配置原理说明

官网配置文件能配置的属性参照

  1. SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
  2. @EnableAutoConfiguration作用
    • 利用EnableAutoConfigurationImportSelector给容器中导入组件
    • 可以查看selectImports()方法的内容
    • 获取候选的配置
  3. 以**HttpEncodingAutoConfiguration(Http编码自动配置)**为例解释自动配置原理;
// 表示是一个配置类,也可以给容器中添加组件
@Configuration

// 启动指定类的ConfigurationProperties功能,并将配置文件中对应的值和HttpEncodingProperties绑定起来
// 并把HttpEncodingProperties加入到ioc容器中
@EnableConfigurationProperties(HttpEncodingProperties.class)  

// Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效
// 判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication 

// 判断当前项目有没有这个类CharacterEncodingFilter(SpringMVC中进行乱码解决的过滤器)
@ConditionalOnClass(CharacterEncodingFilter.class)  

// 判断配置文件中是否存在某个配置(spring.http.encoding.enabled),如果不存在,判断也是成立的
// 即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)  
public class HttpEncodingAutoConfiguration {
  
  	// SpringBoot的配置文件映射
  	private final HttpEncodingProperties properties;
  
    // 参数的值从指定的有参构造器中取得
  	public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
		this.properties = properties;
	}
  
  // 在容器中添加一个组件,该组件的某些值需要从properties中获取
  @Bean   
	@ConditionalOnMissingBean(CharacterEncodingFilter.class)
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}
发布了24 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gavinbj/article/details/103303378