1.简介在实际项目开发过程中,我们经常需要从代码中提取一些变量,放到配置文件中,以便更加统一灵活的管理服务配置信息。比如数据库、eureka、zookeeper、redis、mq、kafka等服务组件的连接参数配置,还有我们自定义的项目参数配置变量。当然,其实我们经常会根据现在的业务需求,自定义参数,注入到代码中,灵活使用!SpringBoot项目启用后,默认会先加载bootstrap.properties或bootstrap.yml这两个配置文件(这两个优先级最高);然后它将加载application.properties或application.yml;如果配置了spring.profiles变量,会同时加载对应的application-{profile}.properties或application-{profile}.yml文件。profile是对应的环境变量,比如dev。如果没有配置,会加载profile=default的配置文件。虽然把配置项写在同一个配置文件里没有问题,但是很多时候我们还是希望分开写,这样会更清晰。比如zookeeper的配置写在zookeeper.properties,数据库相关的配置写在datasource.properties等,所以需要设置加载外部配置文件!具体是如何实现的,一起来看看吧!2.代码实践2.1。通过@value注解实现参数加载当我们想将某个变量注入到某个类中时,我们可以简单的通过@value注解来实现参数注入!比如在application.properties文件中,配置一个config.name的变量键,其值为zhangsan//参数定义config.name=zhangsan,然后在对应的类中通过参数@value注入!@RestControllerpublicclassHelloController{@Value("${config.name}")私有字符串配置;@GetMapping("config")publicStringconfig(){returnJSON.toJSONString(config);}}使用@value注解注入配置,通常会有要求注解中的变量必须提前定义在application.properties文件中,否则启动会报错!当然,如果我们不想让它出错,我们可以给它一个默认值xxx,比如:@Value("${config.name:xxx}")privateStringconfig;这样,SpringBoot项目开启就不会报错了!2.2.通过@ConfigurationProperties注解实现参数加载在某些场景下,@value注解并不能满足我们所有的需求。比如参数配置的数据类型是对象或者数组。这时候使用@ConfigurationProperties会是更好的选择!配置一个对象类型的参数比如在application.properties文件中,当我们要配置一个对象类型的参数时,我们可以这样做!//参数定义config2.name=demo_1config2.value=demo_value_1那么,创建配置类Config2,将定义的变量映射到配置类@Component@ConfigurationProperties(prefix="config2")publicclassConfig2{publicStringname;公共字符串值;}读取数据的方式也很简单,直接注入对应的类即可@RestControllerpublicclassHelloController{@AutowiredprivateConfig2config2;@GetMapping("config2")publicStringconfig2(){返回JSON.toJSONString(config2);}}配置一个Map类型的参数比如在application.properties文件中,当我们要配置一个Map类型的参数时,我们可以这样做!//参数定义config3.map1.name=demo_id_1_nameconfig3.map1.value=demo_id_1_valueconfig3.map2.name=demo_id_2_nameconfig3.map2.value=demo_id_2_value然后,创建一个配置类Config3,将定义的变量映射到配置类。@Component@ConfigurationProperties(prefix="config3")publicclassConfig3{privateMapmap1=newHashMap<>();privateMapmap2=newHashMap<>();}read数据的方式,类似吧!@RestControllerpublicclassHelloController{@AutowiredprivateConfig3config3;@GetMapping("config3")publicStringconfig3(){返回JSON.toJSONString(config3);}}配置一个List类型的参数,比如在application.properties文件中,当我们要配置一个List类型的参数时,我们可以这样做!//参数定义config4.userList[0].enable=maillist_1_enableconfig4.userList[0].name=maillist_1_nameconfig4.userList[0].value=maillist_1_valueconfig4.userList[1].enable=maillist_2_enableconfig4.userList[1].name=maillist_2_nameconfig4.userList[1].value=maillist_2_valueconfig4.userList[2].enable=maillist_3_enableconfig4.userList[2].name=maillist_3_nameconfig4.userList[2].value=maillist_3_value然后,创建配置类Config4,将定义的变量映射到配置类。@Component@ConfigurationProperties(prefix="config4")publicclassConfig4{privateListuserList;publicListgetUserList(){返回用户列表;}publicvoidsetUserList(ListuserList){this.userList=userList;}}publicclassUserEntity{私有字符串启用;私有字符串名称;私有字符串值;}读取数据的方式类似!@RestControllerpublicclassHelloController{@AutowiredprivateConfig4config4;@GetMapping("config4")publicStringconfig4(){返回JSON.toJSONString(config4);}}2.3。我们一开始介绍的通过@PropertySource注解实现配置文件加载是的,很多时候,我们是想单独写配置文件。比如zookeeper组件对应的服务配置文件为zookeeper.properties,redis组件对应的服务配置文件为redis.properties等。我们应该如何将这个自定义配置文件加载到Spring容器中呢?其实方法也很简单,通过@PropertySource即可实现!首先我们在resources资源文件夹下创建两个配置文件test.properties和bussiness.properties,内容如下!test.properties文件内容:aaa.a1=aa1123aaa.a2=aa2123aaa.a3=aa3123aaa.a4=aa4123bussiness.properties文件内容:bbbb.a1=bb1123bbbb.a2=bb2123bbbb.a3=bb3123bbbb.a4=bb4123在SpringBoot启动类上只需加载配置文件!@SpringBootApplication@PropertySource(value={"test.properties","bussiness.properties"})publicclassPropertyApplication{publicstaticvoidmain(String[]args){SpringApplication.run(PropertyApplication.class,args);}}read取数据的方式类似!@RestControllerpublicclassHelloController{@Value("${aaa.a2}")privateStringa2;@Value("${bbbb.a1}")私有字符串bbbbA1;@GetMapping("a2")publicStringa2(){返回JSON.toJSONString(a2);}@GetMapping("bbbbA1")publicStringbbbbA1(){返回JSON.toJSONString(bbbbA1);}}如果我们只需要在业务中使用自定义配置文件的值,我们可以这样引入,没有问题;但是如果项目启动的时候需要用到一些自定义变量,这个方法该方法存在一些问题,原因如下:翻译过来的意思是:虽然在@SpringBootApplication上使用@PropertySource似乎是一种在环境中加载自定义资源的方便简单的方式,但我们不建议使用它,因为SpringBoot准备刷新应用程序上下文之前的环境。使用@PropertySource定义的任何键都加载得太晚,无法对自动配置产生任何影响。所以,如果有些参数是启动项变量,建议在application.properties或者application.yml文件中定义,这样是不会有问题的!或者,使用【自定义环境处理类】加载配置文件!2.4.通过自定义环境处理类,加载配置文件的实现方法也很简单。首先创建一个实现了EnvironmentPostProcessor接口的类,然后自己加载配置文件。publicclassMyEnvironmentPostProcessorimplementsEnvironmentPostProcessor{@OverridepublicvoidpostProcessEnvironment(ConfigurableEnvironmentenvironment,SpringApplicationapplication){String[]profiles={"test.properties","bussiness.properties","blog.yml"};for(Stringprofile:profiles){Resourceresource=newClassPathResource(profile);environment.getPropertySources().addLast(loadProfiles(resource));}}privatePropertySource>loadProfiles(Resourceresource){if(!resource.exists()){thrownewIllegalArgumentException("资源"+resource+"不存在");}if(resource.getFilename().contains(".yml")){returnloadYaml(resource);}else{返回loadProperty(资源);}}私有PropertySourceloadProperty(Resource资源){try{Propertiesproperties=newProperties();properties.load(resource.getInputStream());返回新的PropertiesPropertySource(resource.getFilename(),properties);}catch(Exceptionex){thrownewIllegalStateException("加载配置文件失败"+resource,ex);}}privatePropertySourceloadYaml(Resourceresource){try{YamlPropertiesFactoryBeanfactory=newYamlPropertiesFactoryBean();factory.setResources(资源);属性properties=factory.getObject();返回新的PropertiesPropertySource(resource.getFilename(),properties);}catch(Exceptionex){thrownewIllegalStateException("加载配置文件失败"+resource,ex);接下来,在resources资源目录下,我们还需要创建一个文件META-INF/spring.factories,通过spi,将自定义环境处理类加载到Spring处理器中,当项目启动时,会自动调用这个班级!#启用我们的自定义环境处理类org.springframework.boot.env.EnvironmentPostProcessor=com.example.property.env.MyEnvironmentPostProcessor,属于自定义环境处理方式,相对来说更加灵活。先写一个通用的配置文件解析类,支持读取properties和yml文件,然后Inject到Spring容器中,基本一劳永逸!2.5.最后介绍一下yml文件的读取。上面我们多以properties作为案例进行介绍。可能有人踩坑了。使用@PropertySource注解在项目中加载yml文件。结果启动的时候直接报错,因为@PropertySource不支持直接解析yml文件,只能解析properties文件那么如果我想单独解析yml文件,又不想创建【自定义环境处理类】来读取这种文件,应该怎么处理呢?操作方法也很简单,以自定义blog.yml文件为例!blog.yml文件内容:pzblog:name:helloWorld然后,创建一个读取yml文件的配置类@ConfigurationpublicclassConfigYaml{@BeanpublicstaticPropertySourcesPlaceholderConfigurerproperties(){PropertySourcesPlaceholderConfigurerconfigurer=newPropertySourcesPlaceholderConfigurer();YamlPropertiesFactoryBeanyaml=newYamlPropertiesFactoryBean();yaml.setResources(newClassPathResource("blog.yml"));配置器.setProperties(yaml.getObject());返回配置器;}}读取数据的方式类似!@RestControllerpublicclassHelloController{@Value("${pzblog.name}")privateStringpzblogName;@GetMapping("pzblogName")publicStringpzblogName(){returnJSON.toJSONString(pzblogName);}}3.总结本文主要围绕SpringBoot加载配置文件的几种实现进行了总结。如有疏漏,欢迎网友批评指正!四、参考1、springBoot官方文档