spring boot读取yml文件属性,springboot读取自定义yml配置文件

  spring boot读取yml文件属性,springboot读取自定义yml配置文件

  00-1010 1、环境2、YamlPropertiesFactoryBean3、监听事件4、SnakeYml5、jackson-dataformat-yaml总结在上一篇文章中,我们从源码的角度分析了SpringBoot解析Yml配置文件的全过程,所以今天就来实战一下。总结坏街中除了@Value和@ConfigurationProperties之外读取yml配置文件内容的其他方式。

  00-1010 Spring中有一个类环境,可以认为是当前应用运行的环境。它继承了PropertyResolver接口,因此可以用作属性解析器。首先,创建一个具有以下属性的yml文件:

  人:姓名3360 hydragender :男年龄: 18用起来也很简单。只需用@Autowired将其注入到要使用的类中,然后调用其getProperty()方法,根据属性名得到相应的值即可。

  @ RestControllerpublic class Environment controller { @ auto wired private Environment Environment;@ get mapping( env test )private void getEnv(){ system . out . println(environment . getproperty( person . name );system . out . println(environment . getproperty( person . gender ));整数自动关闭=环境。getProperty(person.age ,integer . class);system . out . println(autoClose);String defaultValue=环境。getProperty(person.other ,String.class, default value );System.out.println(默认值);}}从上面的例子可以看出,Environment提供的方法除了简单的获取之外,还可以对检索到的属性值进行类型转换,设置默认值。调用上面的接口,打印结果如下:

  液压18默认值

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

  spring : Profiles 3360 Active 3360 Pro可以通过acceptsProfiles方法检测一个配置文件是否被激活和加载,或者通过getActiveProfiles方法获取所有激活的配置文件。测试界面:

  @ get mapping( getActiveEnv )private void getActiveEnv(){ system . out . println(environment . accepts profiles( pro ));system . out . println(environment . accepts profiles( dev ));string[]active profiles=environment . getactiveprofiles();for(String active profile : active profiles){ system . out . println(active profile);}}打印结果:

  truefalsepro

  00-1010在Spring中,还可以使用YamlPropertiesFactoryBean读取自定义配置的yml文件,而不会被application.yml和它激活的其他配置文件绑定。

  使用时,只需要通过setResources()方法设置自定义yml配置文件的存储路径,然后通过getObject()方法获取Properties对象,就可以通过它获取具体的属性。这里有一个例子:

  @ get mapping( fc test )public

  ic 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的内容:

  

susanfemale{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值:

 

  

nullnull

 

  

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

 

  

@Configurationpublic 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中的属性:

 

  

susanfemale

 

  

除了使用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}}

 

  

 

  

3、监听事件

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

 

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

  

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

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

 

  

@Overridepublic 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前加一个断点,查看环境的变化:

 

  

 

  执行完成后,可以看到配置文件源已经被添加到了环境中:

  

 

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

  

susanfemale

 

  

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

 

  

 

  

4、SnakeYml

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

 

  

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

准备一个yml配置文件:

 

  

person1: name: hydra gender: maleperson2: name: susan gender: female

在使用SnakeYml解析yml时,最常使用的就是load、loadlAll、loadAs方法,这三个方法可以加载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,在解析前先创建两个实体类对象用于接收:

  

@Datapublic class Person {    SinglePerson person1;    SinglePerson person2;}@Datapublic 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))

 

  

SnakeYml其实实现了非常多的功能,这里就不一一列举了,有兴趣的小伙伴可以自己查看一下文档。如果你看了上一篇的文章后跟着翻阅了一下源码,那么你会发现,其实在SpringBoot的底层,也是借助了SnakeYml来进行的yml的解析操作。

 

  

 

  

5、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文件的话,可以调用ObjectMapper的writeValue方法实现:

 

  

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的复杂功能,大家可以在工作中自己去探索使用。

 

  

 

  

 

  

总结

本文介绍了5种读取yml配置文件的方式,前3种依赖于Spring环境,而SnakeYml和Jackson则可以脱离环境独立使用,可以说它们是对@Value和@ConfigurationProperties注解使用的补充。这几种方法的使用场景不同,也各有各的优点,各自具备一些特殊的用法,而我们在工作中更多情况下,要根据具体的用途进行一种方案的选取或多种的搭配使用。

 

  到此这篇关于SpringBoot中5种高大上的yml文件读取方式的文章就介绍到这了,更多相关SpringBoot yml文件读取方式内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: