SpringBoot中配置文件读取

1.准备环境

有如下配置文件,yml格式和properties格式

yml格式(经我测试发现,属性前面的空格两个不行,需要四个空格才能读出来,这应该是yml的语法,并且属性:后面必须有一个空格):

person:
    name: 张三
    age: 18
    birth: 2020/10/1
    maps: {k1: v1,k2: v2}
    lists:
      - item1
      - item2
      - item3
    phone:
      os: ios
      model: iphone11
      price: 9999

properties格式:

person.name= 张三
person.age= 18
person.birth= 2020/10/1
person.maps.k1=  v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone11
person.phone.price= 9999

建立与之对应的类,并实现getter、setter和toString

Person类

public class Person {
    private String name;
    private int age;
    private Date birth;
    private HashMap<String,Object> maps;
    private List<Object> lists;
    private Phone phone;

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

    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;
    }

    public Date getBirth() {
        return birth;
    }

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

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

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

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

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

    public Phone getPhone() {
        return phone;
    }


    public void setPhone(Phone phone) {
        this.phone = phone;
    }
}

Phone类型:

public class Phone {
    private String os;
    private String model;
    private double price;

    @Override
    public String toString() {
        return "Phone{" +
                "os='" + os + '\'' +
                ", model='" + model + '\'' +
                ", price=" + price +
                '}';
    }

    public String getOs() {
        return os;
    }

    public void setOs(String os) {
        this.os = os;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

2.使用@ConfigurationProperties获取配置文件

在Person类上面写注解:@ConfigurationProperties、@Component

@Component: 通过添加 @Component 注解让 Component Scan 扫描到
@ConfigurationProperties(prefix = "person"): # perfix表示通过指定的前缀,绑定配置文件中的配置

@Component   
@ConfigurationProperties(prefix = "person")   # perfix表示
public class Person {
}
这里配置完成后idea会有一个小提示:未配置 Spring Boot 配置注释处理器,此时我们可以将如下配置写入pom文件的dependencies中
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
</dependency>
然后重新生成pom文件运行项目,就可以在配置文件中提示出我们定义的Person类

测试是否配置成功

我们在测试类中进行测试
@SpringBootTest
class ConfigurationDemoApplicationTests {

    @Autowired
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person);
    }
}
运行测试会在控制台中打印出,表示已经配置成功
Person{name='张三', age=18, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v2}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone11', price=9999.0}}

如果我们使用的配置文件是properties,中文会出现乱码,如何解决?

打开idea,将透明的原生到 ASCII 转换勾选上就可以了

3.使用@Value注解获取配置文件

有如下配置:

@Component
public class Person {
    @Value("${person.name}")
    private String name;
    @Value("#{10*2}")
    private int age;
    @Value("1999/1/1")
    private Date birth;
    private HashMap<String,Object> maps;
    private List<Object> lists;
    private Phone phone;
}
测试结果:
Person{name='张三', age=20, birth=Fri Jan 01 00:00:00 CST 1999, maps=null, lists=null, phone=null}

4.@ConfigurationProperties 和 @Value 获取值比较

@ConfigurationProperties @Value
功能 批量注入配置文件的属性 单独指定
松散绑定 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型(map、list) 支持 不支持
松散绑定:

比如绑定person.firstName,配置文件中可以写:person.firstName、person.first-name、person.first_name、PERSON_FIRST_NAME

SpEL:

#{10*10} 数学计算
#{10>1?"是":"否"} 比较运算
#{field.toString()} 调用方法
#{T(java.lang.Math).PI} 调用静态方法

JSR303数据校验:

必须使用@ConfigurationProperties

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
    @Email
    private String name;
}

@Value相对来说更加灵活,有如下情况,我们只需要person.name

@Value("${person.name}")
private String personName;
@RequestMapping("/hello")
public String index(){
    return "hello"+personName;
}

访问 /hello 可以返回:hello张三

5. 加载指定的配置文件 @PropertySource

有时候我们并不想把某些配置放在全局的配置文件下,比如我们将person配置放在 resource 目录下:

person.properties
person.name= 李四
person.age= 30
person.birth= 2020/10/1
person.maps.k1=  v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone12
person.phone.price= 11111

那么应该如何读取呢?在配置类上新增:@PropertySource(value = {"classpath:person.properties"})

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

运行测试,控制台打印如下:

Person{name='李四', age=30, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v1}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone12', price=11111.0}}

6. 通过@ImportResource实现xml配置的装载,导入Spring的配置文件,让配置文件里的内容生效

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;SpringBoot所有的bean装载全部通过java配置实现,那么一直以来习惯的xml配置是否就没有了用武之地呢,答案是否定的

在项目中增加一个services/HelloService类

在resource目录下增加一个配置文件

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.qingtian.configurationdemo.services.HelloService"></bean>
</beans>

编写单元测试方法

@Autowired
ApplicationContext context;

@Test
public void testHelloService(){
    System.out.println(context.containsBean("helloService"));
}

运行单元测试,控制台打印是:false

SpringBoot中没有Spring的配置文件,而且我们自己写的配置文件,也不能自动识别,如何让配置文件生效呢?

@ImportResource(locations = {"classpath:beans.xml"})
public class ConfigurationDemoApplication {
}

再次运行测试方法,控制台打印:true

SpringBoot不推荐编写xml配置文件,更推荐使用全注解的方式

编写我们的配置类 config/MyConfig

@Configuration  //指明当前类是一个配置类,就是来代替之前的Spring的配置文件
public class MyConfig {

    //将方法的返回值添加到容器中,容器默认的id就是方法名
    @Bean
    public HelloService helloService(){
        return new HelloService();
    }
}

7.配置文件中的占位符

RandomValuePropertiSource:配置文件中可以使用随机数

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

属性配置占位符

app.name=myapp
app.description=${app.name} is a Spring Boot application

-- 可以在配置文件中引用前面配置过的属性
-- ${app.name:默认值}来指定找不到属性时的默认值

8.通过Profile配置SpringBoot项目的不同环境

当我们需要在开发、测试、生产系统不断切换时,如果只有一个配置文件,那会相当的麻烦,使用Profile对不同环境提供不同配置功能,可以通过激活、指定参数等方式快速切换环境

多profile文件形式:

--格式:application-{profile}.properties

  • application-dev.properties
  • application-prod.properties

多profile文档块模式(yml文件支持):

server:
  port: 8000
spring:
  profiles:
    active: dev
---
server:
  port: 8001
spring:
  profiles: dev
---
server:
  port: 80
spring:
  profiles: prod

激活方式:

  • 命令行 --spring.profiles.active=dev
  • 配置文件 spring.profiles.active=dev
  • jvm参数 -Dspring.profiles.active=dev

9.配置文件的加载位置

  • SpringBoot启动会扫描以下位置的application.properties或application.yml文件作为SpringBoot的默认配置文件
    • file: ./config/
    • file: ./
    • classpath: /config/
    • classpath: /
    • 以上是按照 优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容
    • 我们也可以通过配置spring.config.location来改变默认配置

10.外部配置加载顺序

SpringBoot支持多种外部配置方式(优先级由高到低)

  • 命令行参数
  • 来自java:com/env的JNDI属性
  • Java系统属性(System.getProperties())
  • 操作系统环境变量
  • RandomValuePropertySource配置的random.*属性值
  • jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  • jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  • jar包外部的application.properties或application.yml(不带spring.profile)配置文件
  • jar包内部的application.properties或application.yml(不带spring.profile)配置文件
  • @Configuration注解类上的@PropertySource
  • 通过SpringApplication.setDefaultProperties指定的默认属性
posted @ 2020-08-15 20:27  等一个,晴天  阅读(685)  评论(0编辑  收藏  举报