spring boot配置文件@ConfigurationProperties@Value@ConfigurationProperties@Configuration和 Profile

Posted 猎人在吃肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot配置文件@ConfigurationProperties@Value@ConfigurationProperties@Configuration和 Profile相关的知识,希望对你有一定的参考价值。

文章目录

1、配置文件

SpringBoot 中核心思想是 约定 > 配置 > 编码

SpringBoot使用一个全局的配置文件,配置文件名是固定的;

  • application.properties
  • application.yml

配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;

2、YAML语法:

2.1、什么是YAML

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>标签

<server>
	<port>8081</port>
</server>

2.2、基本语法

格式:
k:(空格)v 表示一对键值对(值前面的空格必须有)

层级关系
使用缩进表示层级关系。
只允许用空格的缩进来控制层级关系;不允许使用Tab键。

空格的数量
空格的数量是不限定的。只要左对齐即可,都是同一个层级的

示例:

server:
    port: 8081
    path: /hello

大小写敏感度:
属性和值是大小写敏感的。

2.2、YAML的写法

2.2.1、字面量

字面量 就是单个的、不可再分的普通的值 ,包括 数字,字符串,布尔。

写法:​k: v
​字符串 默认 不用加上 单引号 或者 双引号 。

2.2.2、对象、Map(属性和值)(键值对):

​k: v:在下一行来写对象的属性和值的关系;注意缩进。
​对象还是k: v的方式

friends:
  lastName: zhangsan
  age: 20

行内写法:

friends: lastName: zhangsan,age: 18

2.2.3、数组(List、Set):

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

pets:
 - cat
 - dog
 - pig

行内写法

pets: [cat,dog,pig]

2.3 YAML中 单引号 和 双引号的区别

2.3.1、双引号(按照特殊字符串的原义输出)

双引号: 不会转义字符串里面的特殊字符。特殊字符会作为本身想表示的意思显示出来。

示例:

name: "zhangsan \\n lisi"

输出:

zhangsan
 lisi

2.3.2、单引号(原样,按字符串输出)

单引号:会转义特殊字符。特殊字符被转换成一个普通的字符串。

示例:

name: 'zhangsan \\n lisi' 

输出:

zhangsan \\n  lisi

3、配置文件值注入

3.1 @ConfigurationProperties 读取 application.yml 的配置

@ConfigurationProperties 注解 说明:

1、将配置文件中配置的每一个属性的值,映射到这个组件中。

2、只能加载全局配置文件(application.yml、application.properties), 绑定属性值。

3、支持 数据校验。如不能为空,长度,正则等校验;
4、支持复杂的数据类型;
5、支持松散语法,如@Value("$person.lastName")@Value("$person.last-name") 二者效果一样 。

3.1.1、示例

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

application.yml :

person:
    lastName: hello
    age: 18
    boss: true
    birth: 2017/12/12
    maps: k1: v1,k2: 12
    lists:
      - lisi
      - zhaoliu
    dog:
      name: 小狗
      age: 12

Person.java

@Component  //必须是容器时,@ConfigurationProperties 注解才生效
@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;

	//...getter/setter...

Dog.java

public class Dog 

	private String name;
	private Integer age;
	//...getter/setter...

说明:

  1. @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
  2. prefix = "person":指定配置文件中person下面的所有属性进行一一映射
  3. @Component:只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能。

测试:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBoot02ConfigApplication.class)
public class SpringBoot02ConfigApplicationTests 

	@Autowired
	Person person;
	
	@Test
	public void contextLoads() 
		System.out.println(person.toString());
	

运行结果:

Person [lastName=zhangsan, age=18, boss=true, birth=Sun Dec 03 00:00:00 CST 2017, maps=k1=v1, k2=v2, lists=[lisi, zhaoliu], dog=Dog [name=小狗, age=12]]

3.1.2、将 application.yml 改写 application.properties

application.yml :

person:
    lastName: hello
    age: 18
    boss: true
    birth: 2018/5/14
    maps: k1: v1,k2: 12
    dog:
      name: 小毛
      age: 3

application.yml 的内容 等价于 application.properties 配置,如下 :

application.properties :

person.lastName=张三
person.age=18
person.boss=true
person.birth=2018/5/14
person.maps.k1=v1
person.maps.k2=v2
person.dog.name=小毛
person.dog.age=3

除了 application.properties 配置不一样外,基他代码与yml完全相同。

测试:

运行结果:

Person [lastName=zhangsan, age=18, boss=true, birth=Sun Dec 03 00:00:00 CST 2017, maps=k1=v1, k2=v2, lists=[lisi, zhaoliu], dog=Dog [name=小狗, age=12]]

3.1.3、application.properties 乱码的解决方法

application.properties 配置时,打印显示内容是乱码的解决如下:

设置 properties的默认编码为 utf-8,如图:

3.2、@Value 读取 application.properties

说明:
@Value 支持表达式 、 支持 布尔值。

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

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person 

	@Value("$person.lastName")
	private String lastName;
	
	@Value("#3*7")     //支持表达式 @Value("#  ") 
	private Integer age;
	
	@Value("$person.boss")   //支持 布尔值
	private Boolean boss;

	private Date birth;

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

application.properties 内容与上面一致。

测试

运行结果:

Person [lastName=张三, age=21, boss=true, birth=null, maps=null, lists=null, dog=null]

3.3、 @Value@ConfigurationProperties 比较

3.3.1、@ConfigurationProperties@Validated 的数据校验

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

import javax.validation.constraints.Email;

import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

@Component
@ConfigurationProperties(prefix="person")
@Validated
public class Person 

	@Length(min=14,max=20)
	private String lastName;

	private Integer age;
	private Boolean boss;
	private Date birth;

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

测试

运行结果:

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to com.atguigu.springboot.bean.Person failed:

    Property: person.lastName
    Value: 张三
    Origin: class path resource [application.properties]:1:17
    Reason: 长度需要在14和20之间

说明:

  1. @Component:只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能。
  2. @Validated:数据校验的注解
  3. @Length(min=14,max=20) 校验规则

3.3.2、@ConfigurationProperties 与 @Value 比较

功能@ConfigurationProperties@Value
批量注入配置一个注解就实现值的批量注入一个个指定属性的值
松散绑定(松散语法)@Value("$person.lastName")
@Value("$person.last-name") 二者效果一样
不支持
SpEL不支持支持 @Value("#3*7")
JSR303数据校验支持(是否为空,长度,格式等校验)不支持
复杂类型封装支持不支持

3.3.3、使用 yml, 还是 properties 配置文件 ?

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

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

3.4、@PropertySource()@ConfigurationProperties() 配合使用,加载指定的配置文件

@ConfigurationProperties 的缺点:只能加载全局配置文件(application.properties、application.yml), 绑定属性值。

@PropertySource 的优势:

  • 加载指定的配置文件(如 person.properties );
  • @PropertySource(value = "classpath:person.properties") 中 value 是个数组,可以加载多个文件。

@PropertySource()@ConfigurationProperties() 如何绑定值?

  1. @PropertySource(value = "classpath:person.properties") 加载指定的配置文件到容器中 ;
  2. @ConfigurationProperties(prefix="person") 通过 prefix 指定对应的配置信息,将键值绑定到对应的属性上。

注意:
只能加载 xxx.properties ,不加加载 xxx.yml

依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

person.properties :

person.lastName=李四
person.age=18
person.boss=true
person.birth=2018/5/14
person.maps.k1=v1
person.maps.k2=v2
person.dog.name=小毛
person.dog.age=3

Person.java

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

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

@Component
@PropertySource(value = "classpath:person.properties")
@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;
	
	// getter/setter 省略

测试:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.atguigu.springboot.bean.Person;

@RunWith(SpringRunner.class)
//@SpringBootTest
@SpringBootTest(classes = SpringBoot02ConfigApplication.class)
public class SpringBoot02ConfigApplicationTests 

	@Autowired
	Person person;
	
	@Test
	public void contextLoads() 
		System.out.println(person.toString());
	

运行结果:

Person [lastName=李四, age=18, boss=true, birth=Mon May 14 00:00:00 CST 2018, maps=k2=v2, k1=v1, lists=null, dog=Dog [name=小毛, age=3]]

3.5、@ImportResource(locations="classpath:beans.xml") 添加组件 (不推荐)

Spring Boot 里面没有 Spring 的配置文件,我们自己编写的配置文件(如 beans.xml),也不能自动识别;
@ImportResource 可以加载Spring 的配置文件,使其生效。
参数 locations 是个数组,用于指定具体路径下的多个文件。

HelloSevice.java :

package com.xxx.springboot.service;

public class HelloService 


beans.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloService" class="com.xxx.springboot.service.HelloService"></bean>
</beans>

SpringBoot02ConfigApplication.java :

@ImportResource(locations = "classpath:beans.xml")
@SpringBootApplication
public class SpringBoot02ConfigApplication 

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

说明:
增加 @ImportResource(locations = "classpath:beans.xml") 注解到 Application 类上面

测试:

SpringBoot02ConfigApplicationTests.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;

import com.atguigu.springboot.bean.Person;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBoot02ConfigApplication.class)
public class SpringBoot02ConfigApplicationTests 
	@Autowired
	ApplicationContext ioc;	
	@Test
	public void testHelloService() 
		boolean b = ioc.containsBean("helloService");
		System.out.println(b);
		

运行结果:

true

3.6、@Configuration@Bean 添加组件 (推荐)

SpringBoot 推荐给容器中添加组件的方式;推荐使用全注解的方式:

  1. @Configuration:指明当前类是一个配置类,就是来替代之前的 Spring配置文件(如:bean.xml、applicationContext.xml)
  2. @Bean 相当于配置文件中用标签添加组件

MyAppConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.atguigu.springboot.service.HelloService;

@Configuration
public class MyAppConfig 

	/**
	 * 将方法的返回值HelloService 添加到容器中;容器中这个组件默认的id就是方法名
	 * @return
	 */
	@Bean
    public HelloService helloService02()
        System.out.println("配置类@Bean给容器中添加组件了...");
        return new HelloService();
    

SpringBoot02ConfigApplication.java 恢复原状,即删除上一步配置的@ImportResource

@SpringBootApplication
public class SpringBoot02ConfigApplication 

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

测试:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;

import com.atguigu.springboot.bean.Person;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBoot02ConfigApplication.class)
public class SpringBoot02ConfigApplicationTests 

	@Autowired
	Person person;

	@Autowired
	ApplicationContext ioc;

	@Test
	public void testHelloService() 
		boolean b = ioc.containsBean("helloService02");
		System.out.println(b);
	

	@Test
	public void contextLoads() 
		System.out.println(person.toString());
	

运行结果:

配置类@Bean给容器中添加组件了...
true

4、配置文件占位符 $

4.1、随机数

$random.value、$random.int、$random.long
$random.int(10)、$random.int[1024,65536]

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

application.properties

person.lastName=张三$random.uuid
person.age=$random.int
person.boss=true
person.birth=2018/5/14
person.maps.k1=v1
person.maps.k2=v2
person.dog.name=$person.lastName的小毛
person.dog.age=3

Person.java :

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

@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;
	// getter/setter

测试:

import org.junit.Test;
import org.junit以上是关于spring boot配置文件@ConfigurationProperties@Value@ConfigurationProperties@Configuration和 Profile的主要内容,如果未能解决你的问题,请参考以下文章

spring boot集成redis

Spring零配置之@Configuration注解详解

RepositoryRestMvcConfiguration 的 ObjectMapper 与 Spring Boot 默认的 ObjectMapper?

具有不可变属性的@ConstructorBinding 不适用于 Spring Boot Kotlin 中的 @Value @ConfigurationProperties

Spring Boot参考教程Spring Boot配置使用之配置文件用法

Spring引导外部的外部属性