溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現SpringBoot加載配置文件

發(fā)布時間:2022-03-23 11:25:42 來源:億速云 閱讀:434 作者:小新 欄目:開發(fā)技術

這篇文章主要為大家展示了“如何實現SpringBoot加載配置文件”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“如何實現SpringBoot加載配置文件”這篇文章吧。

    一、簡介

    在實際的項目開發(fā)過程中,我們經常需要將某些變量從代碼里面抽離出來,放在配置文件里面,以便更加統(tǒng)一、靈活的管理服務配置信息。比如,數據庫、eureka、zookeeper、redis、mq、kafka 等服務組件的連接參數配置,還有我們自定義的項目參數配置變量。

    當然,實際上根據當前的業(yè)務需求,我們往往會自定義參數,然后注入到代碼里面去,以便靈活使用!

    今天,我們就一起來聊一聊SpringBoot加載配置文件的幾種玩法!

    SpringBoot 項目在啟用時,首先會默認加載bootstrap.properties或者bootstrap.yml這兩個配置文件(這兩個優(yōu)先級最高);接著會加載application.properties或application.yml;如果何配置了spring.profiles這個變量,同時還會加載對應的application-{profile}.properties或者application-{profile}.yml文件,profile為對應的環(huán)境變量,比如dev,如果沒有配置,則會加載profile=default的配置文件。

    雖然說配置項都寫在同一個配置文件沒有問題,但是很多時候我們仍然希望能分開寫,這樣會比較清晰,比如zookeeper的配置寫在zookeeper.properties,數據庫相關的配置寫在datasource.properties等等,因此就需要設置加載外部配置文件!

    具體該如何實現呢,我們一起來看看!

    二、代碼實踐

    2.1、通過@value注解實現參數加載

    當我們想要在某個類里面注入某個變量,通過@value注解就可以簡單實現參數的注入!

    例如application.properties文件里,配置一個config.name的變量key,值為zhangsan;

    //參數定義
    config.name=zhangsan

    然后在對應的類里面,通過參數@value注入即可!

    @RestController
    public class HelloController {
     
        @Value("${config.name}")
        private String config;
    
        @GetMapping("config")
        public String config(){
            return JSON.toJSONString(config);
        }
    }

    使用@value注解注入配置,通常情況下有個要求就是,注解里面的變量,必須在application.properties文件里面事先定義好,否則啟動報錯!

    當然,如果我們不想讓它抱錯,我們可以給它一個缺省值xxx,比如:

    @Value("${config.name:xxx}")
    private String config;

    這樣,SpringBoot 項目在啟用時不會報錯!

    2.2、通過@ConfigurationProperties注解實現參數加載

    某些場景下,@value注解并不能滿足我們所有的需求,比如參數配置的數據類型是一個對象或者數組,這個時候才用@ConfigurationProperties會是一個比較好的選擇!

    配置一個對象類型的參數

    例如在application.properties文件里,當我們想配置一個對象類型的參數,我們可以這樣操作!

    //參數定義
    config2.name=demo_1
    config2.value=demo_value_1

    然后,創(chuàng)建一個配置類Config2,用于將定義的變量映射到配置類里面。

    @Component
    @ConfigurationProperties(prefix = "config2")
    public class Config2 {
    
        public String name;
    
        public String value;
    
        //...get、set
    }

    讀取數據的方式,也很簡單,直接注入到對應的類里面就可以了;

    @RestController
    public class HelloController {
     
        @Autowired
        private Config2 config2;
    
        @GetMapping("config2")
        public String config2(){
            return JSON.toJSONString(config2);
        }
    }

    配置一個Map類型的參數

    例如在application.properties文件里,當我們想配置一個 Map 類型的參數,我們可以這樣操作!

    //參數定義
    config3.map1.name=demo_id_1_name
    config3.map1.value=demo_id_1_value
    config3.map2.name=demo_id_2_name
    config3.map2.value=demo_id_2_value

    然后,創(chuàng)建一個配置類Config3,用于將定義的變量映射到配置類里面。

    @Component
    @ConfigurationProperties(prefix = "config3")
    public class Config3 {
    
        private Map<String, String> map1 = new HashMap<>();
    
        private Map<String, String> map2 = new HashMap<>();
    
        //...get、set
    }

    讀取數據的方式,與之類似!

    @RestController
    public class HelloController {
     
        @Autowired
        private Config3 config3;
    
        @GetMapping("config3")
        public String config3(){
            return JSON.toJSONString(config3);
        }
    }

    配置一個List類型的參數

    例如在application.properties文件里,當我們想配置一個 List 類型的參數,我們可以這樣操作!

    //參數定義
    config4.userList[0].enable=maillist_1_enable
    config4.userList[0].name=maillist_1_name
    config4.userList[0].value=maillist_1_value
    
    config4.userList[1].enable=maillist_2_enable
    config4.userList[1].name=maillist_2_name
    config4.userList[1].value=maillist_2_value
    
    config4.userList[2].enable=maillist_3_enable
    config4.userList[2].name=maillist_3_name
    config4.userList[2].value=maillist_3_value

    然后,創(chuàng)建一個配置類Config4,用于將定義的變量映射到配置類里面。

    @Component
    @ConfigurationProperties(prefix = "config4")
    public class Config4 {
    
        private List<UserEntity> userList;
    
        public List<UserEntity> getUserList() {
            return userList;
        }
    
        public void setUserList(List<UserEntity> userList) {
            this.userList = userList;
        }
    }
    public class UserEntity {
    
        private String enable;
        private String name;
        private String value;
    
        //...get、set
    }

    讀取數據的方式,與之類似!

    @RestController
    public class HelloController {
     
        @Autowired
        private Config4 config4;
    
        @GetMapping("config4")
        public String config4(){
            return JSON.toJSONString(config4);
        }
    }

    2.3、通過@PropertySource注解實現配置文件加載

    正如我們最開始所介紹的,很多時間,我們希望將配置文件分卡寫,比如zookeeper組件對應的服務配置文件是zookeeper.properties,redis組件對應的服務配置文件是redis.properties等等。

    這種自定義的配置文件,我們應該如何加載到Spring容器里面呢?

    其實方法也很簡單,通過@PropertySource就可以實現!

    首先,我們在resources資源文件夾下,創(chuàng)建兩個配置文件test.properties和bussiness.properties,內容如下!

    test.properties文件內容:

    aaa.a1=aa1123
    aaa.a2=aa2123
    aaa.a3=aa3123
    aaa.a4=aa4123

    bussiness.properties文件內容:

    bbbb.a1=bb1123
    bbbb.a2=bb2123
    bbbb.a3=bb3123
    bbbb.a4=bb4123

    在SpringBoot啟動類上加載配置文件即可!

    @SpringBootApplication
    @PropertySource(value = {"test.properties","bussiness.properties"})
    public class PropertyApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(PropertyApplication.class, args);
        }
    }

    讀取數據的方式,與之類似!

    @RestController
    public class HelloController {
     
        @Value("${aaa.a2}")
        private String a2;
    
        @Value("${bbbb.a1}")
        private String bbbbA1;
     
        @GetMapping("a2")
        public String a2(){
            return JSON.toJSONString(a2);
        }
    
        @GetMapping("bbbbA1")
        public String bbbbA1(){
            return JSON.toJSONString(bbbbA1);
        }
    }

    如果我們只是在業(yè)務中需要用到自定義配置文件的值,這樣引入并沒有什么問題;但是如果某些自定義的變量,在項目啟動的時候需要用到,這種方式會存在一些問題,原因如下:

    如何實現SpringBoot加載配置文件

    翻譯過來的意思就是說:

    雖然在@SpringBootApplication上使用@PropertySource似乎是在環(huán)境中加載自定義資源的一種方便而簡單的方法,但我們不推薦使用它,因為SpringBoot在刷新應用程序上下文之前就準備好了環(huán)境。使用@PropertySource定義的任何鍵都加載得太晚,無法對自動配置產生任何影響。

    因此,如果某些參數是啟動項變量,建議將其定義在application.properties或application.yml文件里面,這樣就不會有問題!

    或者,采用【自定義環(huán)境處理類】來實現配置文件的加載!

    2.4、通過自定義環(huán)境處理類,實現配置文件的加載

    實現方法也很簡單,首先,創(chuàng)建一個實現自EnvironmentPostProcessor接口的類,然后自行加載配置文件。

    public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
    
    
        @Override
        public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
            //自定義配置文件
            String[] profiles = {
                    "test.properties",
                    "bussiness.properties",
                    "blog.yml"
            };
    
            //循環(huán)添加
            for (String profile : profiles) {
                //從classpath路徑下面查找文件
                Resource resource = new ClassPathResource(profile);
                //加載成PropertySource對象,并添加到Environment環(huán)境中
                environment.getPropertySources().addLast(loadProfiles(resource));
            }
        }
    
        //加載單個配置文件
        private PropertySource<?> loadProfiles(Resource resource) {
            if (!resource.exists()) {
                throw new IllegalArgumentException("資源" + resource + "不存在");
            }
            if(resource.getFilename().contains(".yml")){
                return loadYaml(resource);
            } else {
                return loadProperty(resource);
            }
        }
    
        /**
         * 加載properties格式的配置文件
         * @param resource
         * @return
         */
        private PropertySource loadProperty(Resource resource){
            try {
                //從輸入流中加載一個Properties對象
                Properties properties = new Properties();
                properties.load(resource.getInputStream());
                return new PropertiesPropertySource(resource.getFilename(), properties);
            }catch (Exception ex) {
                throw new IllegalStateException("加載配置文件失敗" + resource, ex);
            }
        }
    
        /**
         * 加載yml格式的配置文件
         * @param resource
         * @return
         */
        private PropertySource loadYaml(Resource resource){
            try {
                YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
                factory.setResources(resource);
                //從輸入流中加載一個Properties對象
                Properties properties = factory.getObject();
                return new PropertiesPropertySource(resource.getFilename(), properties);
            }catch (Exception ex) {
                throw new IllegalStateException("加載配置文件失敗" + resource, ex);
            }
        }
    }

    接著,在resources資源目錄下,我們還需要創(chuàng)建一個文件META-INF/spring.factories,通過spi方式,將自定義環(huán)境處理類加載到Spring處理器里面,當項目啟動時,會自動調用這個類!

    #啟用我們的自定義環(huán)境處理類
    org.springframework.boot.env.EnvironmentPostProcessor=com.example.property.env.MyEnvironmentPostProcessor

    如何實現SpringBoot加載配置文件

    這種自定義環(huán)境處理類方式,相對會更佳靈活,首先編寫一個通用的配置文件解析類,支持properties和yml文件的讀取,然后將其注入到Spring容器里面,基本上可以做到一勞永逸!

    2.5、最后,我們來介紹一下yml文件讀取

    在上文中,我們大部分都是以properties為案例進行介紹,可能有的人已經踩過坑了,在項目中使用@PropertySource注解來加載yml文件,結果啟動直接報錯,原因是@PropertySource不支持直接解析yml文件,只能解析properties文件。

    那如果,我想單獨解析yml文件,也不想弄一個【自定義環(huán)境處理類】這種方式來讀取文件,應該如何處理呢?

    操作方式也很簡單,以自定義的blog.yml文件為例!

    blog.yml文件內容:

    pzblog:
      name: helloWorld

    然后,創(chuàng)建一個讀取yml文件的配置類

    @Configuration
    public class ConfigYaml {
    
        /**
         * 加載YML格式自定義配置文件
         * @return
         */
        @Bean
        public static PropertySourcesPlaceholderConfigurer properties() {
            PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
            yaml.setResources(new ClassPathResource("blog.yml"));
            configurer.setProperties(yaml.getObject());
            return configurer;
        }
    }

    讀取數據的方式,與之類似!

    @RestController
    public class HelloController {
     
        @Value("${pzblog.name}")
        private String pzblogName;
    
        @GetMapping("pzblogName")
        public String pzblogName(){
            return JSON.toJSONString(pzblogName);
        }
    }

    以上是“如何實現SpringBoot加載配置文件”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI