摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!
一.自动配置
Spring Boot 不单单从 application.properties 获取配置,所以我们可以在程序中多种设置配置属性。按照以下列表的优先级排列:
1.命令行参数
2.java:comp/env 里的 JNDI 属性
3.JVM 系统属性
4.操作系统环境变量
5.RandomValuePropertySource 属性类生成的 random.* 属性
6.应用以外的 application.properties(或 yml)文件
7.打包在应用内的 application.properties(或 yml)文件
8.在应用 @Configuration 配置类中,用 @PropertySource 注解声明的属性文件
9.SpringApplication.setDefaultProperties 声明的默认属性
可见,命令行参数优先级最高。这个可以根据这个优先级,可以在测试或生产环境中快速地修改配置参数值,而不需要重新打包和部署应用。
还有第 6 点,根据这个在多 moudle 的项目中,比如常见的项目分 api 、service、dao 等 moudles,往往会加一个 deploy moudle 去打包该业务各个子 moudle,应用以外的配置优先。
二.自定义属性
在 application.properties 中对应 HomeProperties 对象字段编写属性的 KV 值:
## 家乡属性 Dev home.province=ZheJiang home.city=WenLing home.desc=dev: I'm living in ${home.province} ${home.city}.
这里也可以通过占位符,进行属性之间的引用。
然后,编写对应的 HomeProperties Java 对象:
/** * 家乡属性 * * Created by bysocket on 17/04/2017. */ @Component @ConfigurationProperties(prefix = "home") public class HomeProperties { /** * 省份 */ private String province; /** * 城市 */ private String city; /** * 描述 */ private String desc; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return "HomeProperties{" + "province='" + province + '\'' + ", city='" + city + '\'' + ", desc='" + desc + '\'' + '}'; } }
通过
@ConfigurationProperties(prefix = "home”) 注解,将配置文件中以 home 前缀的属性值自动绑定到对应的字段中。同是用 @Component 作为 Bean 注入到 Spring 容器中。
如果不是用 application.properties 文件,而是用 application.yml 的文件,对应配置如下:
## 家乡属性 home: province: 浙江省 city: 温岭松门 desc: 我家住在${home.province}的${home.city}
键值对冒号后面,必须空一格。
注意这里,就有一个坑了:
application.properties 配置中文值的时候,读取出来的属性值会出现乱码问题。但是 application.yml 不会出现乱码问题。原因是,Spring Boot 是以 iso-8859 的编码方式读取 application.properties 配置文件。
注意这里,还有一个坑:
如果
定义一个键值对 user.name=xxx ,这里会读取不到对应写的属性值。----读到的是系统本身的用户名字。
为什么呢?Spring Boot 的默认 StandardEnvironment 首先将会加载 “systemEnvironment" 作为首个PropertySource. 而 source 即为System.getProperties().当 getProperty时,按照读取顺序,返回 “systemEnvironment" 的值.即 System.getProperty("
user.name")
配置文件:
user.name=zhang
获取配置文件 user.name:
@Value("${user.name}") String name; @Test public void getHomeProperties() { LOGGER.info("\n\n" + homeProperties.toString() + "\n"); LOGGER.info(name); }
获取配置文件 user.name:结果:
三.random.*属性2018-03-23 10:54:13.643 INFO 625 --- [ main] o.s.springboot.property.PropertiesTest : uknowzxt
Spring Boot 通过 RandomValuePropertySource 提供了很多关于随机数的工具类。概括可以生成随机字符串、随机 int 、随机 long、某范围的随机数。
运行 springboot-properties 工程 org.spring.springboot.property.PropertiesTest 测试类的 randomTestUser 方法。多次运行,可以发现每次输出不同 User 属性值:
UserProperties{id=-3135706105861091890, age=41, desc='泥瓦匠叫做3cf8fb2507f64e361f62700bcbd17770', uuid='582bcc01-bb7f-41db-94d5-c22aae186cb4'}
application.yml 方式的配置如下( application.properties 形式这里不写了):
## 随机属性 user: id: ${random.long} age: ${random.int[1,200]} desc: 泥瓦匠叫做${random.value} uuid: ${random.uuid}
四. 多环境配置
很多场景的配置,比如数据库配置、Redis 配置、注册中心和日志配置等。在不同的环境,我们需要不同的包去运行项目。所以看项目结构,有两个环境的配置:
application-dev.properties:开发环境 application-prod.properties:生产环境
Spring Boot 是通过 application.properties 文件中,设置 spring.profiles.active 属性,比如 ,配置了 dev ,则加载的是 application-dev.properties :
# Spring Profiles Active spring.profiles.active=dev
那运行 springboot-properties 工程中 Application 应用启动类,从控制台中可以看出,是加载了 application-dev.properties 的属性输出:
HomeProperties{province='ZheJiang', city='WenLing', desc='dev: I'm living in ZheJiang WenLing.'}
将 spring.profiles.active 设置成 prod,重新运行,可得到 application-prod.properties的属性输出:
HomeProperties{province='ZheJiang', city='WenLing', desc='prod: I'm living in ZheJiang WenLing.'}
根据优先级,顺便介绍下 jar 运行的方式,通过设置 -Dspring.profiles.active=prod 去指定相应的配置:
mvn package java -jar -Dspring.profiles.active=prod springboot-properties-0.0.1-SNAPSHOT.jar
五.通过命令行设置属性
相信使用过一段时间Spring Boot的用户,一定知道这条命令:java -jar xxx.jar --server.port=8888
,通过使用—server.port属性来设置xxx.jar应用的端口为8888。
在命令行运行时,连续的两个减号--
就是对application.properties
中的属性值进行赋值的标识。所以,java -jar xxx.jar --server.port=8888
命令,等价于我们在application.properties
中添加属性server.port=8888
,该设置在样例工程中可见,读者可通过删除该值或使用命令行来设置该值来验证。
通过命令行来修改属性值固然提供了不错的便利性,但是通过命令行就能更改应用运行的参数,那岂不是很不安全?是的,所以Spring Boot也贴心的提供了屏蔽命令行访问属性的设置,只需要这句设置就能屏蔽:SpringApplication.setAddCommandLineProperties(false)
。