Spring Boot学习笔记(二)--Spring Boot配置

二、Spring Boot 配置

1.1 配置文件

SpringBoot使用一个全局的配置文件(配置文件名是固定的):

  • application.properties
  • application.yml

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

YAML(YAML Ain’t Markup Language)

​ YAML A Markup Language : 是一个标记语言;

​ YAML isn’t Markup Language:不是一个标记语言;

标记语言:

​ 以前的配置文件:大多数都是 xxxx.xml 文件;

​ YAML:以数据为中心,比json、xml等更适合做配置文件;

​ YAML:配置例子

server:
  port: 8081

​ XML:

<server>
	<port>8081port>
server>

项目启动后,可以看到端口号修改成8081:
Spring Boot学习笔记(二)--Spring Boot配置_第1张图片

1.2 YAML语法

1、基本语法:

key:(空格)value:表示一对键值对(空格必须要有!!);

以空格的缩进来控制层级关系:只要是左对齐的一列数据,都属于一个层级;

server:
	port: 8081
	path: /hello

属性和值也是大小敏感;

2、值的写法:

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

k: v:字面直接来写:

​ 字符串默认不需要加上双引号或者单引号;

​ “”:双引号:不会转义特殊字符,特殊字符会表达出它本来的意思

​ name:“zhangsan \n lisi”输出:zhangsan 换行 lisi

​ ‘’:单引号:会转义特殊字符,会把特殊字符看作一般字符串输出

​ name:“zhangsan \n lisi”输出:zhangsan \n lisi

对象,Map(属性和值)(键值对);

​ 对象还是k:v的方式。

​ 在下一行来写对象的属性和值,注意空格和缩进:

friends:
		lastName: zhangsan
		age: 18

​ 行内写法:

friends: {lastName: zhangsan,age: 18}
数组(List、Set);

用(空格)-(空格)来表示数组内的一个元素:

pets:
 - cat
 - dog
 - pig

行内写法:

pets: [cat,dog,pig]

1.3 将配置文件中的属性绑定到实体类(JavaBean)中:

1、创建JavaBean:

Spring Boot学习笔记(二)--Spring Boot配置_第2张图片
Person实体类:

package com.ckh.springboot01helloworldquick.bean;


import java.util.Date;
import java.util.List;
import java.util.Map;


public class Person {
    private String lastName;
    private int 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 int getAge() {
        return age;
    }

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

    public boolean isBoss() {
        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;
    }
}

Dog实体类:

package com.ckh.springboot01helloworldquick.bean;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

tips:使用ALT+Insert快捷键可以自动生成getter和setter以及toString函数。

2、编写相应的配置文件(这里为了简便,直接在全局配置文件application.yml文件中编写)

在application.yml中写person对应的属性的值:

person:
  lastName: ckh
  age: 18
  boss: true
  birth: 1998/9/14
  maps: {k1: v1,k2: v2}
  lists:
    - lisi
    - zhaoliu
  dog:
    name: xiaogou
    age: 2

3、使用注解进行配置文件与组件的绑定

Person实体类进行绑定:

@ConfigurationProperties 将该类中的所有属性与配置文件中相关的属性绑定;

@Component只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能

package com.ckh.springboot01helloworldquick.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/*
* @ConfigurationProperties 将该类中的所有属性与配置文件中相关的属性绑定;
* 将配置文件中的属性映射到这个文件中
* prefix = "person" 表示将配置文件中的person下的属性进行一一映射
*
* @Component只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能
* */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastName;
    private int 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 int getAge() {
        return age;
    }

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

    public boolean isBoss() {
        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;
    }
}

注意!!当输入@ConfigurationProperties时上方会出现警告,表示没有相关处理器:
Spring Boot学习笔记(二)--Spring Boot配置_第3张图片

4、在pom文件中导入依赖:
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-configuration-processorartifactId>
            <optional>trueoptional>
        dependency>
5、进行单元测试,看看Person是否拿到了配置文件中的值

在test文件下有个自动创建的单元测试文件:

Spring Boot学习笔记(二)--Spring Boot配置_第4张图片

package com.ckh.springboot01helloworldquick;

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

/*
* Spring Boot 单元测试;
* 可以在测试时进行编码,很方便地进行自动注入等容器的功能;
* */
@SpringBootTest
class SpringBoot01HelloworldQuickApplicationTests {
    @Autowired
    Person person; //自动注入Person

    @Test
    void contextLoads() {
        System.out.println(person);//在控制台打印person实例
    }

}

6、运行单元测试文件,查看是否输出person的值

不要运行整个项目,只需点击左边的run:

Spring Boot学习笔记(二)--Spring Boot配置_第5张图片

运行成功截图,控制台打印person信息:
Spring Boot学习笔记(二)--Spring Boot配置_第6张图片

1.4 @Value获取Bean的属性值

用@Value分别给每一个属性赋值。值可以为字面量,用${}包裹配置文件中的变量,用#{}包裹Spring表达式。

package com.ckh.springboot01helloworldquick.bean;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;


@Component
//@ConfigurationProperties(prefix = "person")
public class Person {
    /*
    * 原本的Spring中配置文件这样写:
    * 
    *     
    * 
    * 其中,标签相当于@Conponent注解,value <=> @Value
    * */
    @Value("${person.last-name}")
    private String lastName;
    @Value("#{11*2}")
    private int age;
    @Value("false")
    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 int getAge() {
        return age;
    }

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

    public boolean isBoss() {
        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;
    }
}

运行单元测试:

Spring Boot学习笔记(二)--Spring Boot配置_第7张图片

1.5 @Value与@ConfigurationsProperties获取值比较

@ConfigurationsProperties @Value
功能 支持属性值from配置文件批量注入to Bean 一个个绑定值
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装(maps,object等) 支持 不支持
  • 什么是松散绑定?

    last-name <=> lastName <=> last_name <=> last_Name

  • 什么是JSR303数据校验?

    使用@Validated进行校验

    @ConfigurationsProperties 支持:

    @Component
    @ConfigurationProperties(prefix = "person")
    // @Validated开启数据校验!!!!
    @Validated
    public class Person {
        //@Email表示必须校验lastName是否为邮箱格式
        @Email
        private String lastName;
        
        private int age;
        private boolean boss;
        private Date birth;
        private Map<String,Object> maps;
        private List<Object> lists;
        private Dog dog;
    ...
    }
    

    此时,lastName值为张三,不符合邮箱格式,会报错:
    Spring Boot学习笔记(二)--Spring Boot配置_第8张图片

    @Value不支持:

    @Component
    
    @Validated
    public class Person {
       
        //@Email表示必须校验lastName是否为邮箱格式
        @Email
        @Value("${person.last-name}")
        private String lastName;
    
        private int age;
        private boolean boss;
        private Date birth;
        private Map<String,Object> maps;
        private List<Object> lists;
        private Dog dog;
    

    使用@Value不会报错:

Spring Boot学习笔记(二)--Spring Boot配置_第9张图片

**总结:**

如果说,我们只是在某个业务逻辑中需要获取一个配置文件中的某项值,使用@Value;

如果说,我们专门编写了一个JavaBean来和配置文件进行映射,使用@ConfigurationsProperties;

1.6 @PropertySource & @ImportResource

1、@PropertySource

加载指定的配置文件;

在resources文件夹下新建一个person.properties文件,将application.properties中的内容复制到person.properties文件中。

application.properties中的原内容去掉!!

person.properties:

person.last-name=李四
person.age=200
person.boss=true
person.birth=2019/9/15
person.maps.k1=v1
person.maps.k2=v2
person.lists=1,2,3
person.dog.name=dog
person.dog.age=5

在Person类中添加@PropertySource(value = {“classpath:person.properties”})

    @Component
    @ConfigurationProperties(prefix = "person")
//@Validated
    @PropertySource(value = {"classpath:person.properties"})
    public class Person {
        ....
    }

注意!!这里不能把@ConfigurationProperties(prefix = “person”)注释掉,必须留着!!全局配置文件里的内容注释掉!!

为啥呢??因为 @ConfigurationProperties(prefix = “person”)表示该类的属性值为配置中的属性值,找前缀为person的属性。首先从全局配置文件中找是否有person对应的属性值,如果有那么就输出全局配置中的属性值;如果没有,@PropertySource意思是属性来源,从@PropertySource指定的路径中找到对应的配置文件,进行赋值。

2、@ImportResource

导入spring的配置文件,让配置文件里的内容生效;

1、创建一个名为beans.xml 的spring配置文件:
Spring Boot学习笔记(二)--Spring Boot配置_第10张图片

2、创建一个service.HelloService

3、在beans.xml配置文件中加入如下代码:

<bean id="HelloService" class="com.ckh.springboot01helloworldquick.service.HelloService">

bean>

4、在测试单元中测一下容器中有没有HelloService这个组件

test单元测试代码:

    @Autowired
    ApplicationContext ioc;//自动注入ioc容器
    
    @Test
    void testHelloService(){
        Boolean b = ioc.containsBean("helloService");//看容器中是否包含名为helloService的Bean
        System.out.println(b);//控制台打印输出
    }

5、运行,控制台输出false:
Spring Boot学习笔记(二)--Spring Boot配置_第11张图片

这说明,我们自己编写的spring配置文件,spring boot无法自动识别。

要想配置文件生效,加载进来,那么, @ImportResource标注在一个配置类上

package com.ckh.springboot01helloworldquick;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

//@ImportResource导入配置文件beans.xml,让其生效
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class SpringBoot01HelloworldQuickApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot01HelloworldQuickApplication.class, args);
    }

}

Spring Boot学习笔记(二)--Spring Boot配置_第12张图片

Spring Boot推荐给容器中添加组件的方式:推荐使用全注解的方式。

1、配置类---------Spring配置文件

创建一个配置类:config.MyAppConfig

使用@Bean给容器添加组件

package com.ckh.springboot01helloworldquick.config;

import com.ckh.springboot01helloworldquick.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
* @Configuration指明这个类为配置类;就是来替代之前的spring配置文件
*
* 在配置文件中用给容器中添加组件
* */
@Configuration
public class MyAppConfig {

    // 使用@Bean注解给容器中添加组件,(添加的组件为方法的返回值HelloService类),组件的id为方法名helloService
    @Bean
    public HelloService helloService(){
        System.out.println("@Bean给容器中添加组件。。。。");
        return new HelloService();
    }
}

1.7 配置文件占位符

Spring Boot学习笔记(二)--Spring Boot配置_第13张图片

1、随机数

${random.value}\${random.int}\${random.long}
${random.int(10)}\${random.int[1024,65536]}

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

person.last-name=李四${random.uuid}
person.age=${random.int}
person.boss=true
person.birth=2019/9/15
person.maps.k1=v1
person.maps.k2=v2
person.lists=1,2,3
person.dog.name=${person.hello:hello}_dog 
# person.dog.name输出hello_dog

#person.dog.name=${person.hello}_dog
#这里person.hello之前没有定义过,但是也没用:赋默认值,则认定为字面量字符串,直接输出${person.hello}_dog 

person.dog.age=5

1.8 Profile

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

1、多profile文件形式:

我们在编写主配置文件时,文件名可以是 application**-{profile}**.properties/yml

可以创建多个配置文件,默认使用application.properties配置文件。

application.properties: 首选
server.port=8080   

application-dev.properties:
server.port=8081

application-prod.properties:
server.port=8082

2、yml支持多文档块方式

application.yml:

---
server:
  port: 8080
spring:
  profiles:
    active: prod
---
server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: prod
---

3、激活指定profile

​ 1、在主配置文件application.properties中指定需要激活的环境:

spring.profiles.active=dev

​ 2、在application.yml中:第一个文档块中指定激活的环境

spring:
  profiles:
    active: prod

​ 3、命令行:

​ 将当前项目打成jar包后,在cmd中进入所在目录,输入命令:

​ java -jar spring-boot-01-helloworld-quick-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

​ 也可以直接在测试的时候,配置传入命令参数;

Spring Boot学习笔记(二)--Spring Boot配置_第14张图片
​ 4、虚拟机参数

​ -Dspring.profiles.active=dev
Spring Boot学习笔记(二)--Spring Boot配置_第15张图片

1.9 配置文件的加载位置

Spring Boot学习笔记(二)--Spring Boot配置_第16张图片

  • spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件:

    • 文件的根目录下的config文件夹下:file:…/config/
    • 文件的根目录下:file:…/
    • 类路径下的config文件夹下:classpath:/config/
    • 类路径下:classpath:/
      Spring Boot学习笔记(二)--Spring Boot配置_第17张图片
  • 优先级由高到低,高优先级的配置会覆盖低优先级的配置;

  • Spring boot 会从这四个位置全部加载主配置文件,并不是高优先级加载完了低优先级就不加载了:互补配置

    比如,在低优先级配置文件中配置项目的访问路径:

    server.port=8081
    # 配置项目的访问路径
    # 注意这里spring boot2.0以上版本必须加上.servlet才生效
    server.servlet.context-path=/boot02
    

    那么,浏览器中输入localhost:8084/boot02/hello才能得到正确的界面。(这里建一个简单的controller处理“/hello”请求即可)

我们还可以通过spring.config.location改变默认的配置文件位置:

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;

指定配置文件和默认加载的这些配置文件共同起作用,形成互补配置。这里外部指定的配置文件优先级最高;

​ 将项目打包,进入Terminal,运行如下命令:

java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.config.location=‪F:\application.prope
rties

外部配置文件把端口号改为8085;那么,浏览器输入localhost:8085/boot02/hello即可返回数据。

1.10 外部配置加载顺序

Spring Boot也可以从以下位置加载配置文件,优先级从高到低,高优先级覆盖低优先级,但是所有配置文件构成互补配置。

Spring Boot学习笔记(二)--Spring Boot配置_第18张图片

1、命令行参数:

把项目打成jar包,然后在命令行终端运行命令:

java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

多个配置参数用空格分开,参数:–配置项=值

启动后,会看到服务器在8087号端口启动。

6、7、8、9:

先加载带profile的配置文件,由jar包外向jar包内寻找;

再加载不带profile的配置文件,由jar包外向jar包内寻找。

1.11 自动配置原理

由于时间不够,急需做项目,配置原理这节就没有看。

视频链接P18

1.12 @Conditional & 自动配置报告

视频链接P19

你可能感兴趣的:(spring,boot,spring,boot,java)