• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

多种yml/properties配置文件读取方式

武飞扬头像
CloverAn
帮助2

yml/properties配置文件读取方式

推荐使用技巧中,第6个方案,比较灵活,代码规整方便,冗余较少。

问题列表:
1、static 变量。使用@Value和@ConfigurationProperties,不能直接给static变量赋值,他们是调用的默认get/set方法进行赋值的,这时候只需要将默认的get/set方法中的static 去除。@ConfigurationProperties可以放在默认的类注解上,@Value可以加到get/set方法上。

1.使用 @Value 读取配置文件

使用 @Value 可以读取单个配置项,

注解在Springboot项目中都是获取默认配置文件的属性值

如下代码所示:

@SpringBootApplication

  public class DemoApplication implements InitializingBean {

      @Value("${profile.name}")

      private String name;

      public static void main(String[] args) {

          SpringApplication.run(DemoApplication.class, args);

      }

      @Override

      public void afterPropertiesSet() throws Exception {

          System.out.println("My Profile Name:"   name);

      }

  }

有些时候我们需要给参数设置默认值,可以如下操作:

    @Value("${profile.empty:KONG}")
    private String empty;

在需要设置默认值的系统属性名后,加:符号。紧接着,在:右边设置默认值。

建议大家平时在使用@Value时,尽量都设置一个默认值。如果不需要默认值,宁可设置一个空。比如:

@Value("${profile.empty:}")
private String empty;
注意: @Value注解中指定的系统属性名,必须存在,且必须跟配置文件中的相同。

更多用法详见使用技巧。

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

@ConfigurationProperties 和 @Value 的使用略微不同,@Value 是读取单个配置项的,而 @ConfigurationProperties 是读取一组配置项的,我们可以使用 @ConfigurationProperties 加实体类读取一组配置项。
注意,@ConfigurationProperties默认是调用非static Setter方法,把静态的Setter方法的static去掉就可以了

@ConfigurationProperties 是寻找的是全局配置文件,可以读取为Map

注解在Springboot项目中都是获取默认配置文件的属性值

如下代码所示:

yml文件写法:

profile:
  name: test
  desc: test
  demo:
  		a: 11111
  		b: 22222
  		c: 33333

代码:

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

  @Component
  @ConfigurationProperties(prefix = "profile")
  @Data
  public class Profile {
      private String name;
      private String desc;
      private Map<String, String> demo ;
  }

其中 prefix 表示读取一组配置项的根 name,相当于 Java 中的类名,最后再把此配置类,注入到某一个类中就可以使用了,如下代码所示:

@SpringBootApplication
public class DemoApplication implements InitializingBean {
      @Autowired
      private Profile profile;
      
      public static void main(String[] args) {
          SpringApplication.run(DemoApplication.class, args);
      }

      @Override
      public void afterPropertiesSet() throws Exception {
          System.out.println("Profile Object:"   profile);
      }
  }

3.使用 @PropertySource 读取配置文件

使用 @PropertySource 注解可以用来指定读取某个配置文件,比如指定读取 application.properties 配置文件的配置内容,里面有一个参数 value,可以指定很多个配置文件,所以是使用一个数组{},具体实现代码如下:

中文乱码

如果配置文件中出现中文乱码的情况,可通过指定编码格式的方式来解决中文乱码的问题,具体实现如下:

@PropertySource(value = "dev.properties", encoding = "utf-8")

注意事项

@PropertySource 注解默认是不支持yml配置文件读取的,需要修改重写才可以,默认只支持 properties 格式配置文件的读取的。

properties 内容:

user.userName= root
user.isAdmin= true

使用@PropertySource(“classpath:xxxx.properties”)获取对应的properties文件,再用@ConfigurationProperties(prefix = “user”)进行属性映射:

@Data
@Component
@PropertySource("classpath:xxxx.properties")
@ConfigurationProperties(prefix = "user")
public class User {
    private String userName;
    private boolean isAdmin;
}
 

更多用法详见使用技巧

4.使用原生方式读取配置文件

我们还可以使用最原始的方式 Properties 对象来读取配置文件,如下代码所示:

  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.nio.charset.StandardCharsets;
  import java.util.Properties;

  @SpringBootApplication
  public class DemoApplication implements InitializingBean {

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

      @Override
      public void afterPropertiesSet() throws Exception {
          Properties props = new Properties();
          try {
              InputStreamReader inputStreamReader = new InputStreamReader(
                      this.getClass().getClassLoader().getResourceAsStream("application.properties"),
                      StandardCharsets.UTF_8);
              props.load(inputStreamReader);
          } catch (IOException e1) {
              System.out.println(e1);
          }
          System.out.println("Properties Name:"   props.getProperty("profile.name"));
      }
  }

5、Environment

在Spring Core中有一个类Environment,它可以被认为是当前应用程序正在运行的环境,它继承了PropertyResolver接口,因此可以作为一个属性解析器使用。先创建一个yml文件,属性如下:

person:
  name: hydra
  gender: male
  age: 18

使用起来也非常简单,直接使用@Autowired就可以注入到要使用的类中,然后调用它的getProperty()方法就可以根据属性名称取出对应的值了。

@RestController
public class EnvironmentController {
    @Autowired
    private Environment environment;

    @GetMapping("envTest")
    private void getEnv(){
        System.out.println(environment.getProperty("person.name"));
        System.out.println(environment.getProperty("person.gender"));

        Integer autoClose = environment
            .getProperty("person.age", Integer.class);
        System.out.println(autoClose);
        String defaultValue = environment
            .getProperty("person.other", String.class, "defaultValue");
        System.out.println(defaultValue);
    }
}

在上面的例子中可以看到,除了简单的获取外,Environment提供的方法还可以对取出的属性值进行类型转换、以及默认值的设置,调用一下上面的接口,打印结果如下:

hydra
male
18
defaultValue

除了获取属性外,还可以用来判断激活的配置文件,我们先在application.yml中激活pro文件:

spring:
  profiles:
    active: pro

可以通过acceptsProfiles方法来检测某一个配置文件是否被激活加载,或者通过getActiveProfiles方法拿到所有被激活的配置文件。测试接口:

@GetMapping("getActiveEnv")
private void getActiveEnv(){
    System.out.println(environment.acceptsProfiles("pro"));
    System.out.println(environment.acceptsProfiles("dev"));

    String[] activeProfiles = environment.getActiveProfiles();
    for (String activeProfile : activeProfiles) {
        System.out.println(activeProfile);
    }
}

打印结果:

true
false
pro

6、YamlPropertiesFactoryBean

在Spring中还可以使用YamlPropertiesFactoryBean来读取自定义配置的yml文件,而不用再被拘束于application.yml及其激活的其他配置文件。

在使用过程中,只需要通过setResources()方法设置自定义yml配置文件的存储路径,再通过getObject()方法获取Properties对象,后续就可以通过它获取具体的属性,下面看一个例子:

@GetMapping("fcTest")
public void ymlProFctest(){
    YamlPropertiesFactoryBean yamlProFb = new YamlPropertiesFactoryBean();
    yamlProFb.setResources(new ClassPathResource("application2.yml"));
    Properties properties = yamlProFb.getObject();
    System.out.println(properties.get("person2.name"));
    System.out.println(properties.get("person2.gender"));
    System.out.println(properties.toString());
}

查看运行结果,可以读取指定的application2.yml的内容:

susan
female
{person2.age=18, person2.gender=female, person2.name=susan}

但是这样的使用中有一个问题,那就是只有在这个接口的请求中能够取到这个属性的值,如果再写一个接口,不使用YamlPropertiesFactoryBean读取配置文件,即使之前的方法已经读取过这个yml文件一次了,第二个接口取到的仍然还是空值。来对这个过程进行一下测试:

@Value("${person2.name:null}")
private String name;
@Value("${person2.gender:null}")
private String gender;

@GetMapping("fcTest2")
public void ymlProFctest2(){
    System.out.println(name);
    System.out.println(gender);
}

先调用一次fcTest接口,再调用fcTest2接口时会打印null值:

null
null

想要解决这个问题也很简单,可以配合PropertySourcesPlaceholderConfigurer使用,它实现了BeanFactoryPostProcessor接口,也就是一个bean工厂后置处理器的实现,可以将配置文件的属性值加载到一个Properties文件中。使用方法如下:

@Configuration
public class PropertyConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer 
            = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yamlProFb 
            = new YamlPropertiesFactoryBean();
        yamlProFb.setResources(new ClassPathResource("application2.yml"));
        configurer.setProperties(yamlProFb.getObject());
        return configurer;
    }
}

再次调用之前的接口,结果如下,可以正常的取到application2.yml中的属性:

susan
female

除了使用YamlPropertiesFactoryBean将yml解析成Properties外,其实我们还可以使用YamlMapFactoryBean解析yml成为Map,使用方法非常类似:

@GetMapping("fcMapTest")
public void ymlMapFctest(){
    YamlMapFactoryBean yamlMapFb = new YamlMapFactoryBean();
    yamlMapFb.setResources(new ClassPathResource("application2.yml"));
    Map<String, Object> map = yamlMapFb.getObject();
    System.out.println(map);
}

打印结果:

{person2={name=susan, gender=female, age=18}}

同时在setResources时,可以传递多个值,底层源码实现为:

    public void setResources(Resource... resources) {
        this.resources = resources;
    }

7、监听事件

在上篇介绍原理的文章中,我们知道SpringBoot是通过监听事件的方式来加载和解析的yml文件,那么我们也可以仿照这个模式,来加载自定义的配置文件。

首先,定义一个类实现ApplicationListener接口,监听的事件类型为ApplicationEnvironmentPreparedEvent,并在构造方法中传入要解析的yml文件名:

public class YmlListener implements 
    ApplicationListener<ApplicationEnvironmentPreparedEvent> {
    private String ymlFilePath;
    public YmlListener(String ymlFilePath){
        this.ymlFilePath = ymlFilePath;
    }
    //...
}

自定义的监听器中需要实现接口的onApplicationEvent()方法,当监听到ApplicationEnvironmentPreparedEvent事件时会被触发:

@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
    ConfigurableEnvironment environment = event.getEnvironment();
    ResourceLoader loader = new DefaultResourceLoader();
    YamlPropertySourceLoader ymlLoader = new YamlPropertySourceLoader();
    try {
        List<PropertySource<?>> sourceList = ymlLoader
            .load(ymlFilePath, loader.getResource(ymlFilePath));
        for (PropertySource<?> propertySource : sourceList) {
            environment.getPropertySources().addLast(propertySource);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

上面的代码中,主要实现了:

  • 获取当前环境Environment,当ApplicationEnvironmentPreparedEvent事件被触发时,已经完成了Environment的装载,并且能够通过event事件获取
  • 通过YamlPropertySourceLoader加载、解析配置文件
  • 将解析完成后的OriginTrackedMapPropertySource添加到Environment

修改启动类,在启动类中加入这个监听器:

public static void main(String[] args) {
    SpringApplication application = new SpringApplication(MyApplication.class);
    application.addListeners(new YmlListener("classpath:/application2.yml"));
    application.run(args);
}

在向environment中添加propertySource前加一个断点,查看环境的变化,执行完成后,可以看到配置文件源已经被添加到了环境中。

启动完成后再调用一下接口,查看结果:

susan
female

能够正确的取到配置文件中的值,说明自定义的监听器已经生效。

8、SnakeYml

前面介绍的几种方式,在Spring环境下无需引入其他依赖就可以完成的,接下来要介绍的SnakeYml在使用前需要引入依赖,但是同时也可以脱离Spring环境单独使用。先引入依赖坐标:

<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.23</version>
</dependency>

准备一个yml配置文件:

person1:
  name: hydra
  gender: male
person2:
  name: susan
  gender: female

在使用SnakeYml解析yml时,最常使用的就是loadloadlAllloadAs方法,这三个方法可以加载yml文件或字符串,最后返回解析后的对象。我们先从基础的load方法开始演示:

public void test1(){
    Yaml yaml=new Yaml();
    Map<String, Object> map =
            yaml.load(getClass().getClassLoader()
                    .getResourceAsStream("snake1.yml"));
    System.out.println(map);
}

运行上面的代码,打印Map中的内容:

{person1={name=hydra, gender=male}, person2={name=susan, gender=female}}

接下来看一下loadAll方法,它可以用来加载yml中使用---连接符连接的多个文档,将上面的yml文件进行修改:

person1:
  name: hydra
  gender: male
---
person2:
  name: susan
  gender: female

在添加了连接符后,尝试再使用load方法进行解析,报错显示发现了另一段yml文档从而无法正常解析,

这时候修改上面的代码,使用loadAll方法:

public void test2(){
    Yaml yaml=new Yaml();
    Iterable<Object> objects = 
        yaml.loadAll(getClass().getClassLoader()
            .getResourceAsStream("snake2.yml"));
    for (Object object : objects) {
        System.out.println(object);
    }
}

执行结果如下:

{person1={name=hydra, gender=male}}
{person2={name=susan, gender=female}}

可以看到,loadAll方法返回的是一个对象的迭代,里面的每个对象对应yml中的一段文档,修改后的yml文件就被解析成了两个独立的Map。

接下来再来看一下loadAs方法,它可以在yml解析过程中指定类型,直接封装成一个对象。我们直接复用上面的snake1.yml,在解析前先创建两个实体类对象用于接收:

@Data
public class Person {
    SinglePerson person1;
    SinglePerson person2;
}

@Data
public class SinglePerson {
    String name;
    String gender;
}

下面使用loadAs方法加载yml,注意方法的第二个参数,就是用于封装yml的实体类型。

public void test3(){
    Yaml yaml=new Yaml();
    Person person = 
        yaml.loadAs(getClass().getClassLoader().
            getResourceAsStream("snake1.yml"), Person.class);
    System.out.println(person.toString());
}

查看执行结果:

Person(person1=SinglePerson(name=hydra, gender=male), person2=SinglePerson(name=susan, gender=female))

实际上,如果想要将yml封装成实体对象,也可以使用另一种方法。在创建Yaml对象的时候,传入一个指定实体类的构造器对象,然后直接调用load方法就可以实现:

public void test4(){
    Yaml yaml=new Yaml(new Constructor(Person.class));
    Person person = yaml.load(getClass().getClassLoader().
            getResourceAsStream("snake1.yml"));
    System.out.println(person.toString());
}

执行结果与上面相同:

Person(person1=SinglePerson(name=hydra, gender=male), person2=SinglePerson(name=susan, gender=female))

9、jackson-dataformat-yaml

相比大家平常用jackson比较多的场景是用它来处理json,其实它也可以用来处理yml,使用前需要引入依赖:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
    <version>2.12.3</version>
</dependency>

使用jackson读取yml也非常简单,这里用到了常用的ObjectMapper,在创建ObjectMapper对象时指定使用YAML工厂,之后就可以简单的将yml映射到实体:

public void read() throws IOException {
    ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
    InputStream input =
        new FileInputStream("F:\\Work\\yml\\src\\main\\resources\\snake1.yml");
    Person person = objectMapper.readValue(input, Person.class);
    System.out.println(person.toString());
}

运行结果:

Person(person1=SinglePerson(name=hydra, gender=male), person2=SinglePerson(name=susan, gender=female))

如果想要生成yml文件的话,可以调用ObjectMapperwriteValue方法实现:

public void write() throws IOException {
    Map<String,Object> map=new HashMap<>();
    SinglePerson person1 = new SinglePerson("Trunks", "male");
    SinglePerson person2 = new SinglePerson("Goten", "male");
    Person person=new Person(person1,person2);
    map.put("person",person);

    ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
    objectMapper
            .writeValue(new File("F:\\Work\\yml\\src\\main\\resources\\jackson-gen.yml"),map);
}

查看生成的yml文件,可以看到jackson对字符串类型严格的添加了引号,还在文档的开头添加了yml的链接符。至于其他jackson读写yml的复杂功能,大家可以在工作中自己去探索使用。

使用技巧:

1、@Value中 static变量

问题来了,静态变量可以自动注入系统属性值不?

我们一起看看,假如将上面的userName定义成static的:

@Value(“${susan.test.userName}”)
private static String userName;
1
2
程序可以正常启动,但是获取到userName的值却是null。

由此可见,被static修饰的变量通过@Value会注入失败。

作为好奇宝宝的你,此时肯定想问:如何才能给静态变量注入系统属性值呢?

答:这就需要使用如下的骚代码了:

@Service
public class UserService {
	private static String userName;

    @Value("${susan.test.userName}")
    public void setUserName(String userName) {
        UserService.userName = userName;
    }

    public String test() {
        return userName;
    }
}

提供一个静态参数的setter方法,在该方法上使用@Value注入属性值,并且同时在该方法中给静态变量赋值。

有些细心的朋友可能会发现,@Value注解在这里竟然使用在setUserName方法上了,也就是对应的setter方法,而不是在变量上。

2、@Value中数组

众所周知,在Java中的基本数据类型有4类8种,@Value注解对这8中基本类型和相应的包装类,有非常良好的支持,例如:


@Value("${susan.test.a:1}")
private byte a;

@Value("${susan.test.b:100}")
private short b;

@Value("${susan.test.c:3000}")
private int c;

@Value("${susan.test.d:4000000}")
private long d;

@Value("${susan.test.e:5.2}")
private float e;

@Value("${susan.test.f:6.1}")
private double f;

@Value("${susan.test.g:false}")
private boolean g;

@Value("${susan.test.h:h}")
private char h;

@Value("${susan.test.a:1}")
private byte a1;

@Value("${susan.test.b:100}")
private Short b1;

@Value("${susan.test.c:3000}")
private Integer c1;

@Value("${susan.test.d:4000000}")
private Long d1;

@Value("${susan.test.e:5.2}")
private Float e1;

@Value("${susan.test.f:6.1}")
private Double f1;

@Value("${susan.test.g:false}")
private Boolean g1;

@Value("${susan.test.h:h}")
private Character h1;

但只用上面的基本类型是不够的,特别是很多需要批量处理数据的场景中。这时候可以使用数组,它在日常开发中使用的频率很高。

我们在定义数组时可以这样写:

@Value("${susan.test.array:1,2,3,4,5}")
private int[] array;

spring默认使用逗号分隔参数值。

如果用空格分隔,例如:

@Value("${susan.test.array:1 2 3 4 5}")
private int[] array;

spring会自动把空格去掉,导致数据中只有一个值:12345,注意千万别搞错了。

顺便说一下,定义数组的时候,里面还是有挺多门道的。比如上面列子中,我的数据是:1,2,3,4,5。

如果我们把数组定义成:short、int、long、char、string类型,spring是可以正常注入属性值的。

但如果把数组定义成:float、double类型,启动项目时就会直接报错。
定义数组时一定要注意属性值的类型,必须完全一致才可以.

3、@Value中List集合

我们看看List是如何注入属性值的:

yml写法,

sun:
  test:
    list: 10,11,12,13

代码写法:

  @Value("${sun.test.list}")
  private List<Integer> tl;

或者使用Spring的EL表达式功能:

List的定义改成:

@Value("#{'${susan.test.list}'.split(',')}")
private List list;

使用#号加大括号的EL表达式。

然后配置文件改成:

susan.test.list=10,11,12,13

跟定义数组时的配置文件一样。

4、@Value中Set集合

Set也是一种保存数据的集合,它比较特殊,里面保存的数据不会重复。

我们可以这样定义Set:

@Value("#{'${susan.test.set}'.split(',')}")
private Set set;

配置文件是这样的:

susan.test.set=10,11,12,13

Set跟List的用法极为相似。

默认值代码如下:

@Value("#{'${susan.test.set:}'.empty ? null : '${susan.test.set:}'.split(',')}")
private Set set;

5、@Value中Map集合

还有一种比较常用的集合是map,它支持key/value键值对的形式保存数据,并且不会出现相同key的数据。

我们可以这样定义Map:

@Value("#{${susan.test.map}}")
private Map map;

配置文件是这样的:

susan.test.map={"name":"苏三", "age":"18"}

默认值代码如下:

@Value("#{'${susan.test.map:}'.empty ? null : '${susan.test.map:}'}")
private Map map;

6、@ConfigurationProperties读取为实体类

配置文件:

l2cache:
  config:
  	 allowNullValues: true
  	 composite:
     	l1AllOpen: false
     caffeine:
     	refreshPoolSize: 2
     redis:
     	defaultExpiration: 300000

配置实体类:

@Data
@ConfigurationProperties(prefix = "l2cache")
public class L2CacheProperties {
    private L2CacheConfig config;
}

L2CacheConfig :

@Data
public class L2CacheConfig {
    private boolean allowNullValues = true;

    private final Composite composite = new Composite();
    
    private final Caffeine caffeine = new Caffeine();
    
    private final Redis redis = new Redis();
    //以上对应yml配置文件中第三层级的四个属性值
    
    //下面为内部类,是三级层级下的四级层级
    @Data
    public static class Composite {
        private boolean l1AllOpen = false;
    }

    @Data
    public static class Caffeine {
        private Integer refreshPoolSize = Runtime.getRuntime().availableProcessors();
    }

    @Data
    public static class Redis {
        private long defaultExpiration = 0;

    }
}

后续只需要在需要使用的地方,引入配置并自动注入:

@Configuration
@EnableConfigurationProperties(L2CacheProperties.class)
public class CacheRedisCaffeineAutoConfiguration {

 @Autowired
 private L2CacheProperties l2CacheProperties;
 
}

7、@EnableConfigurationProperties配置读取类对象

通过 @EnableConfigurationProperties 注解可以将指定的配置读取类的对象加载到Spring容器,也就是说,在其他配置类上使用一个@EnableConfigurationProperties注解,来将配置文件的参数和RabbitmqProperties类的属性绑定。

@Configuration
@EnableConfigurationProperties(RabbitmqProperties.class)
public class RabbitmqConfig {

    @Autowired
    private RabbitmqProperties prop;
    
    @Bean
    public Rabbitmq rabbitmq() {
        Rabbitmq mq = new Rabbitmq();
        mq.setHost(prop.getHost());
        mq.setPort(prop.getPort());
        mq.setUsername(prop.getUsername());
        mq.setPassword(prop.getPassword());
        return mq;
    }
}

8、@PropertySource加载自定义yml文件

因为spring中PropertySource的默认实现是properties类型文件的解析。

可以实现一个解析yml文件的工具类,实现PropertySourceFactory接口。

第一步:实现工具类

public class YamlPropertySourceFactory implements PropertySourceFactory {
 
    /**
     * PropertySourceFactory针对yml的实现类
     * @param name
     * @param resource
     * @return
     * @throws IOException
     */
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
        return sources.get(0);
    }
}

第二步,配置使用YamlPropertySourceFactory


// 在PropertySource后添加factory指定使用自定义实现的YamlPropertySourceFactory解析yml
@PropertySource(value = {"classpath:xxxx.yml"}, factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "user")
@Component
public class User {
    private String userName;
    private boolean isAdmin;
}

9、YamlPropertiesFactoryBean动态yml及应用

经常在Springboot中,会根据开发需求,分为开发环境dev、测试环境uat、生产环境pro,就会导致我们可能会存在4个配置文件,且会存在根据环境选择使用不同的环境。

在默认的application.yml中配置maven动态环境,具体操作这里不展开。配置文件如下:

spring:
  profiles:
    active: @profiles.active@

在这种情况下,以上三层配置属性是必须存在的,则代码中可以通过动态拼接的方式,实现动态配置文件,代码:

    @Value("${spring.profiles.active}")
    private String profilesActive;

    @Bean
    public YamlConfigTool ymlConfigurerUtil() {
        //1:加载配置文件
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        // 2:将加载的配置文件交给 YamlPropertiesFactoryBean
        yamlPropertiesFactoryBean.setResources(new ClassPathResource(StrUtil.format("application-{}.yml", profilesActive)));
        // 3:将yml转换成 key:val
        Properties properties = yamlPropertiesFactoryBean.getObject();
        // 4: 将Properties 通过构造方法交给我们写的工具类
        return YamlConfigTool.create(properties);
    }

通过上面的方式生成一个实体Bean,然后通过静态方法获取应用配置,代码如下:

import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * @author
 * @date 2020-03-04
 */
public class YamlConfigTool {
    /**
     * ymlProperties
     */
    private static Properties ymlProperties = new Properties();
    public static Properties getYmlProperties() {
        return ymlProperties;
    }
    public static void setYmlProperties(Properties ymlProperties) {
        YamlConfigTool.ymlProperties = ymlProperties;
    }

    /**
     * YamlConfigTool创建
     */
    public static YamlConfigTool create(Properties properties) {
        return new YamlConfigTool(properties);
    }

    public YamlConfigTool(Properties properties) {
        setYmlProperties(properties);
    }

    /**
     * 公共方法
     */
    public static String getStr(String key) {
        return ymlProperties.getProperty(key);
    }
    /**
     * 公共方法
     */
    public static Integer getInt(String key) {
        return Integer.valueOf(ymlProperties.getProperty(key));
    }
    /**
     * 公共方法
     */
    public static Boolean getBoo(String key) {
        return Boolean.valueOf(ymlProperties.getProperty(key));
    }
    /**
     * 公共方法
     */
    public static List<String> getList(String key) {
        return Arrays.asList(ymlProperties.getProperty(key).split(","));
    }
}

至此,YamlConfigTool工具已经可以正常使用了。使用样例代码如下:

方法一:初始化静态常量(接口方式)
@Component
public class CommonTool {
    public interface Param {
    	String BOOTSTRAP_SERVERS = YamlConfigTool.getStr("custom.servers");
    }
     public interface ElasticParam {
        String CLUSTER_NAME = YamlConfigTool.getStr("custom.elastic-param.cluster-name");
    }
}
使用时可以:
String str = CommonTool.Param.BOOTSTRAP_SERVERS;
String str1 = CommonTool.ElasticParam.CLUSTER_NAME;

方式二:直接使用
String str = YamlConfigTool.getStr("spring.profiles.active);
Integer days = YamlConfigTool.getInt("custom.early-warn.days");

10、YamlPropertiesFactoryBean多个yml及应用

在setResources构建的时候,可以传入多个配置文件值:

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import java.util.Properties;

/**
  * @Description: 动态获取yml多环境配置文件数据
  * @Author: CloverAn
  * @Date: 2021/5/17
  */
public class YmlConfigTool {
    private static Properties ymlProperties = new Properties();

    static {
        //1:加载配置文件
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        // 2:将加载的配置文件交给 YamlPropertiesFactoryBean
        yamlPropertiesFactoryBean.setResources(new ClassPathResource("application.yml"));
        // 3:将yml转换成 key:val
        Properties properties = yamlPropertiesFactoryBean.getObject();
        // 4: 通过构造方法交给我们写的工具类,可以传入多个配置文件参数
        yamlPropertiesFactoryBean.setResources(new ClassPathResource("application.yml"), new ClassPathResource(new StringBuilder().append("application-").append(properties.getProperty("spring.profiles.active")).append(".yml").toString()));
        ymlProperties = yamlPropertiesFactoryBean.getObject();
    }

    public static Properties getYmlProperties() {
        return ymlProperties;
    }

    public static void setYmlProperties(Properties ymlProperties) {
       YmlConfigTool.ymlProperties = ymlProperties;
    }

    public static YmlConfigTool create(Properties properties) {
        return new YmlConfigTool(properties);
    }

    public YmlConfigTool(Properties properties) {
        setYmlProperties(properties);
    }

    public static String getStr(String key) {
        return ymlProperties.getProperty(key);
    }

    public static Integer getInt(String key) {
        return Integer.valueOf(ymlProperties.getProperty(key));
    }

    public static Boolean getBoolean(String key) {
        return Boolean.valueOf(ymlProperties.getProperty(key));
    }
}

使用样例:

import org.springframework.stereotype.Component;

@Component
public class YmlConfigToolConstants {
    public  interface  test{
        String TEST = YmlConfigTool.getStr("demo.test");
    }
}

文章收集时间比较久,有些已经找不到实际原链接,如果有问题请联系我。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfkkeea
系列文章
更多 icon
同类精品
更多 icon
继续加载