美文网首页Spring boot
SpringBoot配置文件.yaml和.properties

SpringBoot配置文件.yaml和.properties

作者: 三也视界 | 来源:发表于2020-11-06 15:09 被阅读0次

    很多优秀的框架都有自己的配置文件, 比如hibernate有hbm,mybatis 有properties配置文件。
    Springboot使用一个全局的配置文件,而且配置文件的名字是固定的。 有两种

    • application.properties
    • application.yml

    springboot 配置文件的作用是用来 修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好; 像我们Tomcat 启动 默认配置端口是8080 . 如果要修改, 我们就在这两个文件的一种中来修改,

    • YML (也叫YAML : YAM Ain't Markup Language)**

    YAML Ain't Markup Language 这是一个递归写法 ;

    1. YAML A Markup Language:是一个标记语言
    2. YAML isn't Markup Language:不是一个标记语言;

    标记语言: 我们以前用的配置文件,大多都使用 xxxx.xml 文件 ;

    YAML : 是一种以数据为中心的配置文件, 比json,xml 等更适合做配置文件

    举个栗子:

    以 修改端口为例 :

    yml : 
    server:
      port: 8081
    
    xml :
    <server>
        <port>8081</port>
    </server> 
    

    xml 配置 将太多的浪费在了标签上面。

    yml 基本语法:

    k:(空格)v:表示一对键值对(空格必须有);
    以 空格 的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的

    server:
        port: 8081 
        path: /hello
    

    属性和值也是大小写敏感;

    值的写法:

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

    k: v:字面直接来写;
    字符串默认不用加上单引号或者双引号;

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

        name:   "zhangsan \n lisi":输出;zhangsan 换行  lisi
    

    '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

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

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

    friends:
            lastName: zhangsan
            age: 20
    行内写法: 
    friends: {lastName: zhangsan,age: 18}
    
    • 配置文件注入

    javaBean :

    image

    可以导入配置文件处理器依赖,以后编写配置就会有代码提示;

    image.png

    代码展示配置文件注入属性值 :

    package com.example.webservice.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") 将本类中的所有属性和配置文件中的相关配置进行绑定
     * prefix ="person  表示对哪个文件进行绑定
     * Component 表示这是一个容器, 只有在容器中  ConfigurationProperties 才能使用
    */
    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
    
         private String name;
         private Integer age;
         private boolean man;
         private Date birth;
         private Map<String,Object>map;
         private List<Object>list ;
         private Son son ;
    
    .....省略get/set  以及toString 方法
    
    }
    
    
    package com.example.webservice.bean;
    
    public class Son {
    
        private String name;
        private Integer age ;
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Son{" + "name='" + name + '\'' + ", age=" + age + '}';
        }
    }
    

    properties文件绑定的写法

    person.name=爸爸
    person.age=45
    person.man=true
    person.birth=2019/8/8
    person.map.k1=h1
    person.map.k2=h2
    person.list=a,1,son
    person.son.name=儿子
    person.son,age=20
    

    yml 文件绑定的写法:

    person:
      name: 爸爸
      age: 25
      birth: 2018/2/8
      man: true
      list:
        - a
        - 2
        - son
      map: {key1:value1,key2:value2}
      son:
        name: 儿子
        age: 5
    

    测试类 : 在我们的test 文件夹下 :

    package com.example.webservice;
    import com.example.webservice.bean.Person;
    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
    public class WebserviceApplicationTests {    
       @Autowired
        Person person;
       @Test
       public void contextLoads() {
          // 直接运行这个方法 ,而不是运行整个程序
           System.out.println(person);                
           System.out.println("********************************************************");
       }
    }
    

    1、什么是yml什么是properties?

    对于刚接触springboot的同学,肯定存在一时搞不清楚yml和properties配置文件有什么区别。首先,无论是yml还是properties,都是SpringBoot配置文件中的一种格式,默认名为application.yml或application.properties ,默认放在resources文件夹下,当然,放在resources/config文件夹下也是可以读取到的。

    2、各自的优点?

    下面我们以配置redis缓存数据库的配置文件为例子进行说明:

    yml格式配置文件:

    image

    properties格式配置文件:

    image

    可以看到,yml格式的配置文件有着可读性更强的树型结构,也更加简洁,但对于新手而言,properties格式的配置文件也是不错的选择,易于理解,总之,两种格式的配置文件殊途同归,springboot项目都可以识别。

    3、yml格式配置文件写法和坑点

    对于properties格式的配置文件,我无需多言,所有学习springboot的同学最开始接触的还是properties格式的配置文件。那么properties格式配置文件如何转yml格式呢?

    (1)不同等级用冒号隔开,次等级前用空格,不能用制表符tab,如spring.redis.host=127.0.0.1配置文件中,spring作为第一级,redis作为第二级.
    (2)如果冒号后是值,则用一个空格将冒号和值隔开。
    (3)坑点:yml格式中一定不要用制表符tab,冒号和值之间一定要有空格。

    4、总结

    两种配置文件在 springboot中都可以识别,用其中一种就可以。如果一个目录下存在两种格式的配置文件,则先读取properties格式的配置文件,后读取yml格式的配置文件。读取到的配置以第一次的为准。

    控制台打印结果 (使用的 yml 配置文件)

    image

    properties配置文件在idea中默认utf-8可能会乱码 。因为spring properties 默认是ASCII 码 ,所以需要将properties 默认编码改为UTP-8 ,再√上旁边的 将其运行时转换为ASCII码;再输入中文就好了

    image

    都改成utf-8 ,再输入中文就好了。

    • @Value获取值和@ConfigurationProperties获取值比较**

    @ConfigurationProperties @Value
    功能 批量注入配置文件中的属性 一个个指定
    松散绑定(松散语法) 支持 不支持
    SpEL 不支持 支持
    JSR303数据校验 支持 不支持
    复杂类型封装 支持 不支持

    配置文件yml还是properties他们都能获取到值;
    如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
    如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

    • 配置文件注入值数据校验

    @Component
    @ConfigurationProperties(prefix = "person")
    @Validated
    public class Person {
    
        /**
         * <bean class="Person">
         *      <property name="name" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
         * <bean/>
         */
    
       //name必须是邮箱格式
        @Email
        //@Value("${person.name}")
        private String name;
        //@Value("#{11*2}")
        private Integer age;
        //@Value("true")
        private Boolean boss;
    
        private Date birth;
        private Map<String,Object> maps;
        private List<Object> lists;
        private Dog dog;
    。。。。。get/set /toString 
    

    @PropertySource&@ImportResource&@Bean
    @PropertySource:加载指定的配置文件;

    /**
     * 将配置文件中配置的每一个属性的值,映射到这个组件中
     * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
     *      prefix = "person":配置文件中哪个下面的所有属性进行一一映射
     *
     * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
     *  @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值;
     *
     */
    @PropertySource(value = {"classpath:person.properties"})
    @Component
    @ConfigurationProperties(prefix = "person")
    //@Validated
    public class Person {
    
        /**
         * <bean class="Person">
         *      <property name="name" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
         * <bean/>
         */
    
       //name必须是邮箱格式
       // @Email
        //@Value("${person.name}")
        private String name;
        //@Value("#{11*2}")
        private Integer age;
        //@Value("true")
        private Boolean boss;
    
    

    @ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
    Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

    想让Spring的配置文件生效,加载进来;就要将 @ImportResource 标注在一个配置类上

    @ImportResource(locations = {"classpath:beans.xml"})//类路径上添加配置类的路径
    导入Spring的配置文件让其生效

    不来编写Spring的配置文件 ,下面这就是我们通常的Spring配置类文件

    <?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.example.webservice.controller.Hello"></bean>
    </beans>
    
    

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

    1、配置类@Configuration------>Spring配置文件

    2、使用@Bean给容器中添加组件

    /**
     * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
     *
     * 在配置文件中用<bean><bean/>标签添加组件
     *
     */
    @Configuration
    public class MyAppConfig {
    
        //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
        @Bean
        public HelloService helloService02(){
            System.out.println("配置类@Bean给容器中添加组件了...");
            return new HelloService();
        }
    }
    
    

    配位文件占位符

    1、随机数

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

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

     properties
      person.name=张三${random.uuid}
      person.age=${random.int}
      person.birth=2017/12/15
      person.boss=false
      person.maps.k1=v1
      person.maps.k2=14
      person.lists=a,b,c
    
    // 如果没有hello这个属性, 则会直接输出 ${person.hello} , 如果加了 ${person.hello:hello}_dog   则会直接赋值 输出
    
    hello_dog 
      person.dog.name=${person.hello:hello}_dog  
      person.dog.age=15
    

    3、Profile
    1、多Profile文件
    我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
    springboot默认使用配置文件为application.properties;

    所以我们在然后在application.properties配置文件中 激活自定义的环境配置文件就可以了从application.properties 加载到application-dev.properties 文件了

    在配置文件中指定 spring.profiles.active=dev

    image image

    2、yml支持多文档块方式

      server:
        port: 8081
      spring:
        profiles:
          active: prod  表示当前激活使用哪个环境  --- 表示环境的分割 ,分成不同的文档块。
      ---
      server:
        port: 8083
      spring:
       profiles: dev
     ---
     server:
       port: 8084
     spring:
       profiles: prod  #指定属于哪个环境
    

    4、激活指定profile
    ​ 1、在配置文件中指定 spring.profiles.active=dev
    ​ 2、命令行:
    ​ java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
    ​ 可以直接在测试的时候,配置传入命令行参数 ,打包好的项目运行的时候指定我们的环境:

    image

    ​ 3、虚拟机参数; 在运行的时候 选择Editor configrations

    image image

    -Dspring.profiles.active=dev

    5、配置文件加载位置

    springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
    –file:./config/     文件路径config目录--->最高优先级
    –file:./       文件路径根目录--->其次
    –classpath:/config/ 类路径config目录--->再其次
    –classpath:/     类路径根目录--->最低优先级

    优先级由高到底,高优先级的配置会覆盖低优先级的配置;
    SpringBoot会从这四个位置全部加载主配置文件:互补配置;
    我们还可以通过spring.config.location来改变默认的配置文件位置
    项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
    进入命令行 :

    java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties(properties的硬盘文件目录)

    6、外部配置加载顺序
    SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
    1.命令行参数
    所有的配置都可以在命令行上进行指定
    java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
    多个配置用空格分开; --配置项=值
    2.来自java:comp/env的JNDI属性
    3.Java系统属性(System.getProperties())
    4.操作系统环境变量
    5.RandomValuePropertySource配置的random.*属性值

    由jar包外向jar包内进行寻找;

    优先加载带profile

    7.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

    8.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

    再来加载不带profile

    9.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

    10.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

    11.@Configuration注解类上的@PropertySource

    12.通过SpringApplication.setDefaultProperties指定的默认属性

    所有支持的配置加载来源;

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    2.yml文件

    name: hha
    age: 60
    friend:
           - good
           - easy
           - bug
    params:
          addr: ZZ
          code: EE
    name: 洗洗
    
    

    3.实体类

    package com.my.last;
    
    import java.util.List;
    import java.util.Map;
    
    public class Student { private String name;
        private int age;
    
        private List<String> friend ;
    
        private Map<String, Object> params; /**
         * @return the name */ public String getName() {
            return name; }
    
        /**
         * @param name the name to set */ public void setName(String name) { this.name = name; }
    
        /**
         * @return the age */ public int getAge() { return age; }
    
        /**
         * @param age the age to set */ public void setAge(int age) { this.age = age; }
    
        /**
         * @return the friend */ public List<String> getFriend() { return friend; }
    
        /**
         * @param friend the friend to set */ public void setFriend(List<String> friend) { this.friend = friend; }
    
        /**
         * @return the params */ public Map<String, Object> getParams() { return params; }
    
        /**
         * @param params the params to set */ public void setParams(Map<String, Object> params) { this.params = params; }
    
        /* (non-Javadoc)
         * @see java.lang.Object#toString() */ @Override
        public String toString() { return "Student [name=" + name + ", age=" + age + ", friend=" + friend + ", params=" + params + "]"; } }
    
    

    4.测试类

    package com.my.last;
    
    import org.yaml.snakeyaml.Yaml;
    
    public class Test { public static void main(String[] args) {
            Yaml yaml = new Yaml();
    
            Student student = yaml.loadAs(Test.class.getResourceAsStream("/test.yml"), Student.class);
            System.out.println(student); }
    } 
    
    

    ** 或者依赖**

    <dependency>
                <groupId>org.jyaml</groupId>
                <artifactId>jyaml</artifactId>
                <version>1.3</version>
            </dependency>
    
    

    解析方法:

            Student student2 = null; try {
                 student2 = org.ho.yaml.Yaml.loadType(Test.class.getResourceAsStream("/test.yml"), Student.class);
            } catch (FileNotFoundException e) { // TODO Auto-generated catch block
     e.printStackTrace();
            }
            System.out.println(student2);</pre>
    

    二者区别

    在于其拥有天然的树状结构,所以着手尝试将properties文件更改为yml文件,发现了几个要注意的地方:
    1、在properties文件中是以”.”进行分割的, 在yml中是用”:”进行分割;
    2、yml的数据格式和json的格式很像,都是K-V格式,并且通过”:”进行赋值;
    3、在yml中缩进一定不能使用TAB,否则会报很奇怪的错误;(缩进特么只能用空格!!!!)
    4、yml每个k的冒号后面一定都要加一个空格;
    5、使用spring cloud的maven进行构造的项目,在把properties换成yml后,一定要进行mvn clean insatll
    6、yml是跨语言的:可以在包括JAVA,go,python等大量的语言中使用,比如做云计算使用go和java的时候,可以通过配置中心使用同一份配置!
    7、支持列表:区别于properties只支持键值对数据,yml配置文件支持列表,如下所示:

    image

    当然,从properties转yml文件会遇到很多坑,在此记录下:

    1,层级关系缩进不能用tab键:每次都数2.4.6这样打空格。。。
    2,每个key的后面需要加:,每个:后面还需要加一个空格!
    3,列表的短横线后面需要有个空格。

    两个关键点:

    第一个是yml是支持中文内容的,properties想使用中文只能用unicode编码

    第二个是顺序问题,properties是不保证加载顺序的,yml有先后顺序,实际用例比如springcloud的zuul网关路由配置,如果一个uri同时满足两个匹配规则,properties你是不知道它到底使用了哪个规则的,而yml则一定是使用了靠的那个路由规则

    Java 的 Properties 加载属性文件后是无法保证输出的顺序与文件中一致的,因为 Properties 是继承自 Hashtable , key/value 都是直接存在 Hashtable 中的,而 Hashtable 是不保证进出顺序的。

    总有时候会有关心顺序一致的需求,恰如有 org.apache.commons.collections.OrderdMap(其实用 LinkedHashMap 就是保证顺序) 一样,我们也想要有个 OrderdProperties。

    详见: https://blog.csdn.net/qq1169091731/article/details/53012071

    Spring Boot中application.properties和application.yml加载顺序

    使用@PropertySource注解加载自定义配置文件,该注解无法加载yml配置文件。使用@Value注解获得文件中的参数值

    application.properties和application.yml文件可以放在一下四个位置:

    • 外置,在相对于应用程序运行目录的/congfig子目录里。
    • 外置,在应用程序运行的目录里
    • 内置,在config包内
    • 内置,在Classpath根目录

    同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:
    [图片上传失败...(image-9f4435-1604553023059)]

    image

    此外,如果你在相同优先级位置同时有application.properties和application.yml,那么application.properties里面的属性就会覆盖里application.yml的属性

    package com.example.webservice.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") 将本类中的所有属性和配置文件中的相关配置进行绑定
     * prefix ="person  表示对哪个文件进行绑定
     * Component 表示这是一个容器, 只有在容器中  ConfigurationProperties 才能使用
    */
    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
    
         private String name;
         private Integer age;
         private boolean man;
         private Date birth;
         private Map<String,Object>map;
         private List<Object>list ;
         private Son son ;
    
    .....省略get/set  以及toString 方法
    
    }
    
    
    package com.example.webservice.bean;
    
    public class Son {
    
        private String name;
        private Integer age ;
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Son{" + "name='" + name + '\'' + ", age=" + age + '}';
        }
    }
    
    
    properties文件绑定的写法
    #注释方法 Ctrl + /
    person.name=爸爸
    person.age=45
    person.man=true
    person.birth=2019/8/8
    person.map.k1=h1
    person.map.k2=h2
    person.list=a,1,son
    person.son.name=儿子
    person.son,age=20
    
    
    yml 文件绑定的写法:
    
    person:
      name: 爸爸
      age: 25
      birth: 2018/2/8
      man: true
      list:
        - a
        - 2
        - son
      map: {key1:value1,key2:value2}
      son:
        name: 儿子
        age: 5测试类 : 在我们的test 文件夹下 :package com.example.webservice;import com.example.webservice.bean.Person;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)@SpringBootTestpublic class WebserviceApplicationTests {    @Autowired     Person person;    @Test    public void contextLoads() {   // 直接运行这个方法 ,而不是运行整个程序        System.out.println(person);        System.out.println("********************************************************");    }
    

    相关文章

      网友评论

        本文标题:SpringBoot配置文件.yaml和.properties

        本文链接:https://www.haomeiwen.com/subject/bgiovktx.html