博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring boot 学习笔记(三)之 配置
阅读量:5272 次
发布时间:2019-06-14

本文共 11935 字,大约阅读时间需要 39 分钟。

一:概述

     在Spring boot 中根据业务需求,我们往往会在不同地方配置我们所需的key-value 配置项,配置文件存在不同的地方的场景如下:

(1) 默认存在 application.properties 或 application.yaml ,而这些文件可以放在项目的不同地方,如:项目根目录下、项目根目录/config下、src/main/resources下、src/main/resources/config下、引用的工程中,甚至这两个文件同时存在;

(2) 针对 (1) 中的 application.properties 或 application.yaml , 又存在不同环境的配置;

(3) 上述的配置文件中可以配置 Spring boot 的 key 配置,如:server.port、spring.datasource.* 配置等,同时也可配置我们自定义的 key ;

(4) 为了不让 application.properties 变得臃肿,我们会将项目所需 的 key 配置放置在自定义的配置文件中,而该配置文件可以向 (1) 中一样放在任何位置上;

二:功能介绍

1、 自定义配置

(1) 自定义配置 存储在 application.xml 或 application.yaml

     使用 @ ConfigurationProperties 注解 或直接使用 @Value 直接进行注解注入属性值

     使用 @ ConfigurationProperties 根据 prefix 注解进来的属性上,可以不加注解,但是需要需要有对应的 setter方法,否则值设置不进去;

     使用 @Value 方法可以没有 setter方法,它是通过别的方式将值设置进去的;

示例如下:

package com.example.demo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /**  * 自定义配置属性注入(配置项存储在 application.properties 中)  *  * @author sandy  *  */ @Component @ConfigurationProperties(prefix = "hello") public class CoustomPropertiesInjectV1 {
    private String username;     @Value("${hello.test.username}")     private String testUsername;               public String getUsername() {
        return username;     }     public void setUsername(String username) {
        this.username = username;     }     public String getTestUsername() {
        return testUsername;     }     public void setTestUsername(String testUsername) {
        this.testUsername = testUsername;     } }

 

@GetMapping("/configurationProperties")     public CoustomPropertiesInjectV1 findPropertiesInjectV1(){
        return propertiesInjectV1;     }

 

说明:

  • 在项目的 src/main/resources 下存在 applicaton.properties文件,在该文件中存在 hello 为前缀的配置项,主要为:
# 自定义配置项hello.username=sandy_classpath_applicaiton_properties hello.test.username=test_classpath_applicaiton_properties

 

  • 针对 hello.username 在  @ConfigurationProperties(批量注入直接,自动注入同个前缀不同配置项) 已经配置了 前缀,表示把前缀为 “hello” 的配置均注入到当前类属性中,但是 仅能将 前缀.XXX 注入到当前类中 同名 XXX 属性中;
  • 在使用 @ConfigurationProperties 时,需要增加 Maven 依赖项:
org.springframework.boot
spring-boot-configuration-processor
true

 

  •      根据上面了解 hello.test.username 是无法通过 前缀注入进来的,因为类中的属性名不能含有 ".",因此 test.username 不能作为属性名,此时可以使用 @Value 进行注入;

根据上面介绍,自定义配置项注入可以使用两个注解:@ConfigurationProperties 或 @Value;

(2) 自定义配置项存在在自定义的配置文件(文件名不为 applicaiton)

    a)  在类上加上注解:@PropertySource,指明加载自定义的配置文件 (仅适用于 properties文件)

package com.example.demo.config;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.springframework.stereotype.Component;/** * 自定义配置属性注入(配置项存储在cutom.properties 中) * 
  • 虽然配置了 @PropertySource,并指明了加载其他文件的配置项,但是实际上仍会去application.properties中加载配置
    * 当该类的配置项key与applicaiton.properties中一致时,加载了 applicaiton.propeties中的同名key属性值; *
  • *
  • 自定义配置文件在类上下文时,value中可加上 classpath 指明文件在类路径下,或者不加这个,也默认是在类路劲下
  • *
  • 加载文件系统文件,自定义配置文件不在类路径下,使用file,默认从项目跟路径下加载
  • *
  • @PropertySource 的value 属性可以指定多个地方的配置文件,若不同文件中存在同名key,则后者覆盖前者
  • * @author sandy * */@PropertySource(value={"classpath:custom.properties","file:config/custom-config-dir.properties"})@Component@ConfigurationProperties(prefix = "hello")public class CoustomPropertiesInjectV2 { private String usernameV2; @Value("${hello.test.usernameV2}") private String testUsernameV2; /***与application.properties 文件存在同名key配置项***/ private String username; @Value("${hello.test.username}") private String testUsername; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getTestUsername() { return testUsername; } public void setTestUsername(String testUsername) { this.testUsername = testUsername; } public String getUsernameV2() { return usernameV2; } public void setUsernameV2(String usernameV2) { this.usernameV2 = usernameV2; } public String getTestUsernameV2() { return testUsernameV2; } public void setTestUsernameV2(String testUsernameV2) { this.testUsernameV2 = testUsernameV2; }}
    @GetMapping("/configurationProperties/V2")    public CoustomPropertiesInjectV2 findPropertiesInjectV2(){        return propertiesInjectV2;    }

     

      配置文件 在 项目目录/config/custom-config-dir.properties 、类路径下/custom.properties

      项目目录/config/custom-config-dir.properties文件内容如下:

    hello.usernameV2=sandy_root_config_dir_custom_propeties hello.test.usernameV2=test_root_config_dir_custom_propeties hello.username=sandy_root_config_dir_custom_propeties hello.test.username=test_root_config_dir_custom_propeties

     

    类路径下/custom.properties 如下:

    hello.usernameV2=sandy_classpath_custom_propeties hello.test.usernameV2=test_classpath_custom_propeties hello.username=sandy_classpath_custom_propeties hello.test.username=test_classpath_custom_propeties

     

    访问 该 restful 接口,返回内容如下:

    {
        "usernameV2": "sandy_root_config_dir_custom_propeties",     "testUsernameV2": "test_root_config_dir_custom_propeties",     "username": "sandy_classpath_applicaiton_properties",     "testUsername": "test_classpath_applicaiton_properties" }

     

    综上可以得到以下结论:

    • 通过 propertiesSource 标签指定加载的配置文件,若没有说要加载 application.properties文件,默认会加载 application.properties文件;
    • 自定义配置文件中存在与 application.properties 中 同名 key,则以application.properties中的同名 key 值为准;
    • propertiesSource  value属性可以指定多个外部文件,不同文件存在同名 key,后加载的覆盖前者同名 key 值;

     b) 自定义文件为 yml文件,装载方式使用 @bean

       在前面基础上增加以下类

    package com.example.demo.config.dto;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Componentpublic class CoustomYamlInjectV1 {    private String usernameV2;    @Value("${yml.test.usernameV2}")   //最终值为  工程目录下/config/custom-config-dir.yml 文件中的值    private String testUsernameV2;        /***与application.properties 文件存在同名key配置项***/    private String username;    @Value("${hello.test.username}")    private String testUsername;   //最终值为 application.properties中的值    @Value("${hello.test.usernameV2}")  //最终值为 config/config/custom-config-dir.properties 文件中的值    private String helloTestUsernameV2;        public String getHelloTestUsernameV2() {        return helloTestUsernameV2;    }    public void setHelloTestUsernameV2(String helloTestUsernameV2) {        this.helloTestUsernameV2 = helloTestUsernameV2;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getTestUsername() {        return testUsername;    }    public void setTestUsername(String testUsername) {        this.testUsername = testUsername;    }    public String getUsernameV2() {        return usernameV2;    }    public void setUsernameV2(String usernameV2) {        this.usernameV2 = usernameV2;    }    public String getTestUsernameV2() {        return testUsernameV2;    }    public void setTestUsernameV2(String testUsernameV2) {        this.testUsernameV2 = testUsernameV2;    }}

     

    package com.example.demo.config;import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;import org.springframework.core.io.ClassPathResource;import org.springframework.core.io.FileSystemResource;/** * 测试加载自定义 yaml文件 * @author sandy * */@Configurationpublic class CoustomYamlConfigV1 {    @Bean    public static PropertySourcesPlaceholderConfigurer loadProperties() {        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();        //yaml.setResources(new FileSystemResource("classpath:config/user.yml"));//File路径引入        yaml.setResources(new ClassPathResource("coustom.yml"),new FileSystemResource("config/custom-config-dir.yml"));//class路径引入        configurer.setProperties(yaml.getObject());        return configurer;    }}

     

    @GetMapping("/yml")    public CoustomYamlInjectV1 findYamlInject(){        return coustomYamlInjectV1;    }

     

    yml配置文件如下:

     src/main/resources/custom.yml

    yml:    usernameV2: sandy_classpath_custom_yml   test:      usernameV2: test_classpath_custom_yml      hello:    usernameV2: sandy_classpath_custom_yml   username: sandy_classpath_custom_yml   test:       usernameV2: hello_test_classpath_custom_yml      username: test_classpath_custom_yml

     

    工程目录下/config/custom-config-dir.yml

    yml:    usernameV2: sandy_root_config_dir_custom_yml   test:      usernameV2: test_root_config_dir_custom_yml      hello:    usernameV2: sandy_root_config_dir_custom_yml   username: sandy_root_config_dir_custom_yml   test:       usernameV2: hello_root_config_dir_custom_yml      username: test_root_config_dir_custom_yml

     

    最终restful 接口返回值如下:

    {    "usernameV2": null,    "testUsernameV2": "test_root_config_dir_custom_yml",    "username": null,    "testUsername": "test_classpath_applicaiton_properties",    "helloTestUsernameV2": "test_root_config_dir_custom_propeties"}

     

    2、application.properties  和 application.yml 共存时

          (1) 当仅在 src/main/resources 存在这两个文件时

    package com.example.demo.config.dto;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Componentpublic class ApplicationPropertiesV1 {    @Value("${day.username}")    private String helloUsername;    @Value("${day.test.username}")    private String helloTestUsername;    public String getHelloUsername() {        return helloUsername;    }    public void setHelloUsername(String helloUsername) {        this.helloUsername = helloUsername;    }    public String getHelloTestUsername() {        return helloTestUsername;    }    public void setHelloTestUsername(String helloTestUsername) {        this.helloTestUsername = helloTestUsername;    }}

     

    @GetMapping("/application")    public ApplicationPropertiesV1 findApplicationInject(){        return applicationPropertiesV1;    }

     

    src/main/resources/applicaiton.properties

    day.username=day_sandy_classpath_applicaiton_propertiesday.test.username=day_test_classpath_applicaiton_properties

     

    src/main/resources/applicaiton.yml

    day:    username: day_sandy_classpath_applicaiton_yml   test:       username: test_classpath_applicaiton_yml

     

    restful 接口调用结果

    {    "helloUsername": "day_sandy_classpath_applicaiton_yml",    "helloTestUsername": "test_classpath_applicaiton_yml"}

     

    说明:

         同在类路径下,properties 的 优先级 高于 yml,同名key以前者中的值为准;

       (2) application 全局配置文件在不同目录下:

    SpringBoot配置文件可以放置在多种路径下,不同路径下的配置优先级有所不同。

    可放置目录(优先级从高到低)
        file:./config/ (当前项目路径config目录下);
        file:./ (当前项目路径下);
        classpath:/config/ (类路径config目录下);
        classpath:/ (类路径config下).
    优先级由高到底,高优先级的配置会覆盖低优先级的配置;出现同名 key 的时候,以优先级高的目录中的配置文件中的值为准;
    SpringBoot会从这四个位置全部加载配置文件并互补配置;

    (2) 中的说明参考链接:https://blog.csdn.net/IT_faquir/article/details/80869578

    (3) application.properties 在依赖包也存在

        本工程中的 application.properties 优先级高于 依赖包中的该配置文件,加载时仅加载本工程中的该配置文件,依赖包中的不会加载。

     

    三:总结

    配置的方式主要有以下几种:

    • 来自 applicaiton开头的配置文件的配置 (properties 或 yml 结尾);

                 a) properties 的配置高于 yml 的配置,两个文件均会加载,但是 同名 key 的以 properties 的值为准;

                 b) 依赖包也存在 application配置文件,同样名称的配置文件 仅会加载一处,本工程中存在,加载本工程中的配置文件,否则加载依赖包中的配置文件;

                 c) application 配置文件放置在本工程不同位置,均会加载,但是对于同名key,优先级从高到低如下:

                            i) file:./config/ (当前项目路径config目录下);

                           ii) file:./ (当前项目路径下);
                           iii) classpath:/config/ (类路径config目录下);
                           iiii) classpath:/ (类路径config下).

    • @propertySource 配置的引入外部文件的配置 文件(非application开头的文件,文件可以存储在类上下文环境中,也可以是在文件系统下,如:在项目工程根目录下),可以配置加载多个外部配置文件,后加载的可以覆盖前面覆盖的同名 key;
    • @Bean 自定义加载 的 PropertySourcesPlaceholderConfigurer,可以加载多个外部配置文件。后加载的可以覆盖前面覆盖的同名 key;

    当遇上同名key的时候,以上三种方式 是从 优先级高到低排列的,同名 key以优先级高的配置方式为准。

     四:未研究问题

    (1) 在上述覆盖配置的场景下,更多的是介绍本工程下出现配置文件出现在不同目录下,若依赖的包中也存在 application.yml配置 或 同文件名的配置文件时,又是怎样加载配置文件的?以及怎样覆盖同名配置项的?

    转载于:https://www.cnblogs.com/sandyflower/p/11408572.html

    你可能感兴趣的文章
    2019-8-5 考试总结
    查看>>
    JS中实现字符串和数组的相互转化
    查看>>
    web service和ejb的区别
    查看>>
    Windows Azure Cloud Service (29) 在Windows Azure发送邮件(下)
    查看>>
    CS61A Efficiency 笔记
    查看>>
    ArcGIS Server Javascript 多图对比功能
    查看>>
    微信上传素材返回 '{"errcode":41005,"errmsg":"media data missing"}',php5.6返回
    查看>>
    div或者p标签单行和多行超出显示省略号
    查看>>
    Elasticsearch 滚动重启 必读
    查看>>
    Hadoop基本概念
    查看>>
    java.util.zip压缩打包文件总结一:压缩文件及文件下面的文件夹
    查看>>
    浅说 apache setenvif_module模块
    查看>>
    MySQL--数据插入
    查看>>
    重新学习python系列(二)? WTF?
    查看>>
    shell脚本统计文件中单词的个数
    查看>>
    SPCE061A学习笔记
    查看>>
    sql 函数
    查看>>
    hdu 2807 The Shortest Path 矩阵
    查看>>
    熟悉项目需求,要知道产品增删修改了哪些内容,才会更快更准确的在该项目入手。...
    查看>>
    JavaScript 变量
    查看>>