尚硅谷SpringBoot课程学习笔记——Spring Boot配置

一、配置文件

1.SpringBoot使用一个全局的配置文件,配置文件名是固定的,SpringBoot有有以下两种方式的配置文件:

  • application.properties
    – 自动生成的文件
    在这里插入图片描述
    修改http服务端口的命令为(SpringBoot默认为8080):
    在这里插入图片描述
  • application.yml
    – 需要手动创建
    在这里插入图片描述
    修改http服务端口的命令为(与application.properties格式不一样):
    在这里插入图片描述

2.配置文件的作用:修改SpringBoot自动配置的默认值。

配置文件放在src/main/resources目录或者类路径/config下

.yml是YAML(YAML Ain’t Markup Language)语言的文件,以数据为中心,比json、xml等更加适合做配置文件。

二、YAML语法

1.基本语法

k:(空格)v:表示一对键值对(空格必须有)
以空格的缩进来控制层级关系,左对齐的一列数据为同一层级

server:
	port:8090
	path:/hello

2.值的写法

1、字面量:普通的值(数字、字符创、布尔)

k: v
字符串默认不用加上单引号或者双引号
“”:双引号,不会转义字符串中的特殊字符(如\n)
‘’:单引号,会转义特殊字符

2、对象、Map(属性和值或者说键值对)

k: v
在下一行来写对象的属性和值的关系,注意缩进缩进
例如

friends:
   name: jack
   age: 23

也可以采用行内写法

friends: {name: jack,age: 23}
3、数组(List、Set)

用(短横线)-值表示数组中的一个元素

language:
	- Java
	- Pathon
	- C++

行内写法

language: [Java,Pathon,C++]

三、yaml配置文件值获取

@ConfigurationProperties: 告诉SpringBoot将本类中所有属性和配置文件中相关的配置进行绑定
通过实验来学习如何从yaml配置文件中获取值,首先是application.yaml中的数据:

1、编写代码

server:
  port:8081
person:
  lastname: zhangsan
  age: 22
  boss: false
  birth: 2020/05/13
  maps: {k1: v1,k2: 12}
  lists: {lisi,zhaoliu}
  dog:
    name: 小狗
    age: 2

在main/java/包下建立两个类
在这里插入图片描述
Person.java代码

package com.yjx.springboot01helloworldquick.bean;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import java.util.List;

/**
 * 将配置文件中配置的每一个属性的值,映射到这个组件中
 * @ConfigurationProperties: 告诉SpringBoot将本类中所有属性和配置文件中相关的配置进行绑定
 * prefix = "person" : 配置文件中哪个与下面的所有属性进行一一映射
 *
 * 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastname;
    private Integer age;
    private Boolean boss;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;

    @Override
    public String toString() {
        return "Person{" +
                "lastname='" + lastname + '\'' +
                ", age=" + age +
                ", boss=" + boss +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                ", dog=" + dog +
                '}';
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getBoss() {
        return boss;
    }

    public void setBoss(Boolean boss) {
        this.boss = boss;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
}

set、get、toString等方法可以通过idea自动实现
alt+insert 打开如下界面
在这里插入图片描述
Dog.java

package com.yjx.springboot01helloworldquick.bean;

public class Dog {
    private String name;
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2、测试

打开test/java下的文件
在这里插入图片描述
添加测试语句

package com.yjx.springboot01helloworldquick;

import com.yjx.springboot01helloworldquick.bean.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * SpringBoot单元测试
 */
@SpringBootTest
class Springboot01HelloworldQuickApplicationTests {
    
    //@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
    @Autowired
    Person person;

    @Test
    void contextLoads() {
        System.out.println(person);
    }

}

点击contextLoads方法左侧的三角形按钮开始测试
在这里插入图片描述
结果显示已从yml配置文件中读取出值。

3、总结

1、@ConfigurationProperties: 告诉SpringBoot将本类中所有属性和配置文件中相关的配置进行绑定,实现从yaml配置文件中获取值;
2、必须是容器中的组件,才能使用容器提供的@ConfigurationProperties功能,所以需要加上@Component注解。

四、properties配置文件编码问题

注释掉yml配置文件中的内容
在application.properties文件中写入配置(与application.yml的配置效果一样)

server.port=8081

# 配置person的值
person.lastname=张三
person.age=23
person.birth=2017/02/12
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=dog
person.dog.age=3

运行发现中文乱码了
在这里插入图片描述
解决方案:将编码改成utf-8
在idea的file->settings->Editor->File Encodding中,配置文件默认是utf-8编码的,需要勾选在运行时将utf-8转换成ASCII格式,再次运行程序即可。
在这里插入图片描述

五、@ConfigurationProperties和@Value的区别

1、区别

@ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散语法绑定(Relaxed binding)支持不支持
Spring表达式语言(SpEL)不支持支持
JSR303数据校验支持不支持
复杂类型封装支持(可以去除map、list中的数据)不支持(仅支持基本类型数据)

如果说,我们只是在业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果,编写了一个javaBean来和配置文件的值进行映射,直接使用@Configuration

属性名匹配规则(Relaxed binding)

  • person.firstName : 标准方式
  • person.first-name : 大写用-,等同于person.firstName
  • person.first_name : 大写用_,等同于person.firstName
  • PERSON_FIRST_NAME : 大写+下划线分隔,推荐用于环境变量或命令行参数

2、@Value使用样例

@RestController
public class sayController {

    @Value("${person.lastname}") //获取配置文件中的值
    private String name;
    @Value("#{11*2}")         //SpEL运算
    private Integer age;
    @Value("true")           //直接设定值
    private boolean boss;
    @RequestMapping("/sayInfo")
    public String sayInfo(){
        return "name:"+name + ", age:"+age+",boss:"+boss;
    }
}

运行结果:
在这里插入图片描述

六、@PropertySource、@Bean

1、@PropertySource

作用: 加载指定的配置文件。
@ConfigurationProperties(prefix = “person”)默认是从全局配置文件中获取值。
测试:
在resources文件夹下新建一个person.properties配置文件,用来存储person的数据(把原来全局配置文件的person数据剪切过来)。

@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastname;
    private Integer age;
    private Boolean boss;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;

2、@Bean

作用:通过配置类给容器添加组件。
测试:
在包下新建service文件夹,文件夹下新建HelloService类;
在包下新建config文件夹,文件下下新建MyConfig类;

//MyConfig.java
import com.yjx.springboot01helloworldquick.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @Configuration :指明当前类是一个配置类
 */
@Configuration
public class MyConfig {
    //将方法的返回值添加到容器中,容器中这个组件默认id就是方法名
    @Bean
    public HelloService helloService(){
        System.out.println("配置类@Bean给容器中添加组件成功");
        return new HelloService();
    }
}

在测试文件的类中添加测试代码

    @Autowired
    ApplicationContext ioc;//ApplicationContext有两种,需导入正确
    @Test
    public void testHelloService(){
        boolean b = ioc.containsBean("helloService");//测试是否存在该组件
        System.out.println(b);
    }

测试结果
在这里插入图片描述

七、配置文件占位符

1、随机数

${random.value}、${random.int}、${random.long}、
${random.int(10)}、${randon.int[1024,65526]}

2、占位符获取之前配置的值,如果没有可以用:指定默认值

# 配置person的值
person.lastname=张三${random.uuid}}
person.age=23
person.birth=2017/02/12
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.lastname}_${person.have:big}_dog
person.dog.age=3

八、Profile

Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境

1、 多profile文件形式:

  • 格式:application-{profile}.properties
    –例如:application-dev.properties、 application-prod.properties
    新建一个application-dev.properties文件,写入以下数据:
server.port=8082

在默认配置文件application.properties里添加spring.profiles.active=dev

server.port=8081
spring.profiles.active=dev

运行程序,可以发现使用的端口号为8082

2、yml支持多文档块模式

server:
  port: 8081
spring:
  profiles:
    active: prod   #激活prod环境
---             #三条短横线用来分离文档块
server:
  port: 8083
spring:
  profiles: dev
---
server:
  port: 8084
spring:
  profiles: prod

运行程序,可以发现用的是prod环境的端口号8084

3、激活方式:

  • 命令行 --spring.profiles.active=dev
    –项目打包为jar包后运行:
java -jar 项目包名.jar --spring.profiles.active=XXX

也可以在测试时,配置传入命令行参数
在这里插入图片描述

  • 在配置文件中指定 spring.profiles.active=dev
  • jvm参数 -Dspring.profiles.active=dev
    在这里插入图片描述

九、配置文件加载位置

springboot启动会扫描一下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件

  • file:./config/ ——当前项目根目录下的config文件里
  • file:./ —— 当前项目的根目录下
  • classpath:/config/ ——resource/config
  • classpath:/ ——默认的情况,类路径(resources)下

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。

可以通过配置spring.config.location来改变默认配置文件位置,项目打包好后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置,这里指定的新的配置文件与项目中的配置文件共同起作用。

十、外部配置的加载顺序

SpringBoot除了可以从项目中的application.properties/application.yml主配置文件中加载配置,还可以从以下位置加载配置:

1、命令行参数:所有的配置都可以在命令行参数中指定,每个配置项前使用–,多个配置间使用空格隔开,例如:

java -jar XXX.jar --server.port=8088 --server.context-path=boot

2、来自java:comp/env的JNDI属性

3、java的系统属性(System.getProperties(""))

4、操作系统环境变量

5、RandomValuePropertySource配置的random.*属性值

6、jar包外部的application-{profile}.properties或application-{profile}.yml(带spring.profile配置)

7、jar包内部的application-{profile}.properties或application-{profile}.yml(带spring.profile配置)

8、jar包外部的application.properties或application.yml(不带spring.profile配置)

9、jar包内部的application.properties或application.yml(不带spring.profile配置)

10、@Configuration注解类上的@PropertySource

11、通过SpringApplication.setDefaultProperties()指定的默认属性

十一、自动配置原理

  1. SpringBoot启动时加载组配置类,开启自动配置功能@EnableAutoConfiguration
  2. @EnableAutoConfiguration的作用是:利用EnableAutoConfigurationImportSelector给容器中导入一些组件

精髓:

  1. SpringBoot启动会加载大量的自动配置类
  2. 看需要的功能有没有SpringBoot默认写好的自动配置类
  3. 看这个自动配置类中配置了哪些组件(要用的组件有的话,就不用再配置了)
  4. 给容易中自动配置类添加组件时,会从properties类中获取某些属性,可以在配置文件中指定这些属性的值。

十二、@Condition & 自动配置报告

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用,才会实例化一个Bean)
@ConditionalOnBean:当容器中有指定Bean的条件下进行实例化。
@ConditionalOnMissingBean:当容器里没有指定Bean的条件下进行实例化。
@ConditionalOnClass:当classpath类路径下有指定类的条件下进行实例化。
@ConditionalOnMissingClass:当类路径下没有指定类的条件下进行实例化。
@ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。
@ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。
@ConditionalOnProperty:当指定的属性有指定的值时进行实例化。
@ConditionalOnExpression:基于SpEL表达式的条件判断。
@ConditionalOnJava:当JVM版本为指定的版本范围时触发实例化。
@ConditionalOnResource:当类路径下有指定的资源时触发实例化。
@ConditionalOnJndi:在JNDI存在的条件下触发实例化。
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。

通过启用debug=true(写在配置文件里),来让控制台打印自动配置报告,可以很方便知道哪些自动配置类生效了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值