属性配置文件
- bean配置文件:spring配置bean的文件。
- java配置文件,通过@Configuration加载
- 原生配置文件,xml定义的配置文件
- 属性配置文件:spring配置key-value的文件
1 properties配置文件
properties默认配置文件
用于配置容器端口名、数据库链接信息、日志级别。pom是项目编程的配置,properties是软件部署的配置。
移除特殊字符、全小写。在环境变量中通过小写转换与.替换_来映射配置文件中的内容,比如:环境变量SPRING_JPA_DATABASEPLATFORM=mysql的配置会产生与在配置文件中设置spring.jpa.databaseplatform=mysql一样的效果。
1
| src/main/resources/application.properties
|
1 2 3 4
| environments.dev.url=http://dev.bar.com environments.dev.name=Developer Setup environments.prod.url=http://foo.bar.com environments.prod.name=My Cool App
|
列表类型
必须使用连续下标索引进行配置。
1 2
| pring.my-example.url[0]=http://example.com spring.my-example.url[1]=http://spring.io
|
1 2
| pring.my-example.url[0]=http://example.com spring.my-example.url[1]=http://spring.io
|
Map类型
Map类型在properties和yaml中的标准配置方式如下:
1 2
| spring.my-example.foo=bar spring.my-example.hello=world
|
使用随机数配置
${random}的配置方式主要有一下几种,读者可作为参考使用。
1 2 3 4 5 6 7 8 9 10
| # 随机字符串 com.didispace.blog.value=${random.value} # 随机int com.didispace.blog.number=${random.int} # 随机long com.didispace.blog.bignumber=${random.long} # 10以内的随机数 com.didispace.blog.test1=${random.int(10)} # 10-20的随机数 com.didispace.blog.test2=${random.int[10,20]}
|
读取规则
将配置文件中的值引入到java程序中。
在Spring应用程序的environment中读取属性的时候,每个属性的唯一名称符合如下规则:
- 通过.分离各个元素
- 最后一个.将前缀与属性名称分开
- 必须是字母(a-z)和数字(0-9)
- 必须是小写字母
- 用连字符-来分隔单词
- 唯一允许的其他字符是[和],用于List的索引
- 不能以数字开头
1
| this.environment.containsProperty("spring.jpa.database-platform")
|
配置提示
引入配置提示的依赖。并在maven插件中,将该依赖排除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| //配置提示,@ConfigurationProperties <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
//打包的时候将处理器排除掉 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>
|
2 yaml配置文件
yaml基本语法
- key: value;kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- ‘#’表示注释
- 字符串无需加引号,如果要加,’’与””表示字符串内容 会被 转义/不转义
1 2 3 4 5 6 7
| environments: dev: url: http://dev.bar.com name: Developer Setup prod: url: http://foo.bar.com name: My Cool App
|
yaml基本类型
- 字面量:单个的、不可再分的值。date、boolean、string、number、null
- 对象:键值对的集合。map、hash、set、object
1 2 3 4 5 6
| 行内写法: k: {k1:v1,k2:v2,k3:v3} #或 k: k1: v1 k2: v2 k3: v3
|
- 数组:一组按次序排列的值。array、list、queue
1 2 3 4 5 6
| 行内写法: k: [v1,v2,v3] #或者 k: - v1 - v2 - v3
|
yaml的实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Data public class Person { private String userName; private Boolean boss; private Date birth; private Integer age; private Pet pet; private String[] interests; private List<String> animal; private Map<String, Object> score; private Set<Double> salarys; private Map<String, List<Pet>> allPets; }
@Data public class Pet { private String name; private Double weight; }
|
对应的yaml配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| # yaml表示以上对象 person: userName: zhangsan boss: false birth: 2019/12/12 20:12:33 age: 18 pet: name: tomcat weight: 23.4 interests: [篮球,游泳] animal: - jerry - mario score: english: first: 30 second: 40 third: 50 math: [131,140,148] chinese: {first: 128,second: 136} salarys: [3999,4999.98,5999.99] allPets: sick: - {name: tom} - {name: jerry,weight: 47} health: [{name: mario,weight: 47}]
|
3 其他配置方式
JVM变量/系统属性
java程序启动参数 -D是用来做什么:
使用空格作为分割符,如果一个key或者value包含空格,则需要双引号。在运行改程序时加上JVM参数-Ddubbo.token=“666” 那么运行之后你可以看到控制台输出了666!一点值得注意的是,需要设置的是JVM参数而不是program参数
1 2 3 4
| java -Dfoo="some string" SomeClass -D"spring.my-example.url[0]=http://example.com" -D"spring.my-example.url[1]=http://spring.io" -Dspring.my-example.url=http://example.com,http://spring.io
|
环境变量
由于环境变量中无法使用[和]符号,所以使用_来替代。任何由下划线包围的数字都会被认为是[]的数组形式。
1 2 3
| MY_FOO_1_ = my.foo[1] MY_FOO_1_BAR = my.foo[1].bar MY_FOO_1_2_ = my.foo[1][2]
|
程序变量
在启动java应用是,添加配置参数。系统属性的绑定也与文件属性的绑定类似,通过[]来标识列表,同样的,他也支持逗号分割的方式
1
| java -jar xxx.jar --server.port=8888
|
4 多环境配置
多环境配置文件
对于多环境的配置,各种项目构建工具或是框架的基本思路是一致的,通过配置多份不同环境的配置文件,再通过打包命令指定需要打包的内容之后进行区分打包。
在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,比如:
- application-dev.properties:开发环境
- application-test.properties:测试环境
- application-prod.properties:生产环境
多配置文件的加载规则
application.yml/properties总是会被加载,不管是否配置spring.profile.active.
- 配置文件的方式。在默认配置文件中application.properties指定环境。最先加载application.yml/properties,然后再按照spring.profile.active加载相应的application-{profile}.yml(properties)。如果application和application-{profile}中键有重复会被application-{profile}替换为最新的。
- Java系统属性方式。在启动jar时指定加载配置(Java系统属性方式)或者通过java代码设置系统属性的方式。
1 2 3 4 5
| java -Dspring.profiles.active=mydev123 -jar SpringBootEnv-1.0.jar
System.setProperty("spring.profiles.active","mydev");
|
- 命令行的方式。在启动jar时指定加载配置(命令行方式)
1
| java -jar SpringBootEnv-1.0.jar --spring.profiles.active=dev56789
|
- 系统环境变量的方式。在启动jar时指定加载配置(系统环境变量方式)。首先增加一个名称为SPRING_PROFILES_ACTIVE的系统环境变量,启动spring程序。
1 2 3
| #当前系统是windows set SPRING_PROFILES_ACTIVE=dev987 java -jar SpringBootEnv-1.0.jar
|
以上四种方式的优先级
1
| 命令行方式 > Java系统属性方式 > 系统环境变量方式 > 配置文件方式
|
如果需要激活多个profile可以使用逗号隔开,
1
| spring.profiles.active=dev,test
|
配置加载顺序
SpringBoot启动会扫描以下位置的application.properties/yml文件作为spring boot的默认配置文件:
1 2 3 4 5 6
| #file: 指当前项目根目录 file:./config/ file:./ #classpath: 指当前项目的resources目录 classpath:/config/ classpath:
|
- 命令行中传入的参数。
- SPRING_APPLICATION_JSON中的属性。SPRING_APPLICATION_JSON是以JSON格式配置在系统环境变量中的内容。
- java:comp/env中的JNDI属性。
- Java的系统属性,可以通过System.getProperties()获得的内容。
- 操作系统的环境变量
- 通过random.*配置的随机属性
- 位于当前应用jar包之外,针对不同{profile}环境的配置文件内容,例如:application-{profile}.properties或是YAML定义的配置文件
- 位于当前应用jar包之内,针对不同{profile}环境的配置文件内容,例如:application-{profile}.properties或是YAML定义的配置文件
- 位于当前应用jar包之外的application.properties和YAML配置内容
- 位于当前应用jar包之内的application.properties和YAML配置内容
- 在@Configuration注解修改的类中,通过@PropertySource注解定义的属性
- 应用默认属性,使用SpringApplication.setDefaultProperties定义的内容1.
5 配置绑定
使用Java程序读取
如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用;
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class getProperties { public static void main(String[] args) throws FileNotFoundException, IOException { Properties pps = new Properties(); pps.load(new FileInputStream("a.properties")); Enumeration enum1 = pps.propertyNames(); while(enum1.hasMoreElements()) { String strKey = (String) enum1.nextElement(); String strValue = pps.getProperty(strKey); System.out.println(strKey + "=" + strValue); } } }
|
@ConfigurationProperties
- 只有在容器中的组件,才会有Springboot的强大功能。
- 从配置文件中自动加载,进行属性配置,然后使用Componet注册
假设在propertes配置中有这样一个配置:
方法一:创建对应的配置类:
1 2 3 4 5 6 7
| @Component @ConfigurationProperties(prefix = "com.didispace") public class FooProperties {
private String foo;
}
|
方法二:通过Binder绑定:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @SpringBootApplication public class Application {
public static void main(String[] args) { ApplicationContext context = SpringApplication.run(Application.class, args);
Binder binder = Binder.get(context.getEnvironment());
FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get(); System.out.println(foo.getFoo()); } }
|
方法三:@EnableConfigurationProperties+ @ConfigurationProperties
- 在配置类上开启属性配置功能。开启car的属性配置功能
- 该中方法对配置类进行修改然后装配。不需要修改类本身的代码。
1 2 3 4
| @EnableConfigurationProperties(Car.class) class MyConfig{
}
|
1 2 3 4 5 6 7
| @ConfigurationProperties(prefix = "com.didispace") public class FooProperties {
private String foo;
}
|
@Value
通过占位符的方式加载自定义的参数
- 注入普通字符;
- 注入操作系统属性;
- 注入表达式运算结果;
- 注入其他Bean的属性;
- 注入文件内容;
- 注入网址内容;
- 注入属性文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
@Configuration @ComponentScan("com.kongzi") @PropertySource("classpath:db.properties") public class ElConfig {
@Value("您好,欢迎访问 carefree 的博客") private String comment;
@Value("#{systemProperties['os.name']}") private String osName;
@Value("#{ T(java.lang.Math).random() * 100.0 }") private double randomNumber;
@Value("#{otherUser.userName}") private String fromUserName; @Value("#{otherUser.blogUrl}") private String fromBlogUrl;
@Value("classpath:info.txt") private Resource testFile;
@Value("https://blog.csdn.net/carefree31441") private Resource testUrl;
@Value("${jdbc.driver}") private String jdbc_driver; @Value("${jdbc.url}") private String jdbc_url; @Value("${jdbc.username}") private String jdbc_username; @Value("${jdbc.password}") private String jdbc_password; @Autowired private Environment environment; @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } public void outputResource() { try { System.out.println("注入普通字符串:"); System.out.println(comment); System.out.println("------------------------------------------------"); System.out.println("注入操作系统属性:"); System.out.println(osName); System.out.println("------------------------------------------------"); System.out.println("注入表达式运算结果:"); System.out.println(randomNumber); System.out.println("------------------------------------------------"); System.out.println("注入其他Bean的属性:"); System.out.println("用户名称:" + fromUserName); System.out.println("博客地址:"+ fromBlogUrl); System.out.println("------------------------------------------------"); System.out.println("注入文件资源:"); System.out.println("文件中的内容:" + IOUtils.toString(testFile.getInputStream())); System.out.println("------------------------------------------------"); System.out.println("注入配置文件(方式一):"); System.out.println("数据库驱动:" + jdbc_driver); System.out.println("数据库连接:" + jdbc_url); System.out.println("数据库用户:" + jdbc_username); System.out.println("数据库密码:" + jdbc_password); System.out.println("------------------------------------------------"); System.out.println("注入配置文件(方式二):"); System.out.println("数据库驱动:" + environment.getProperty("jdbc.driver")); System.out.println("数据库连接:" + environment.getProperty("jdbc.url")); System.out.println("数据库用户:" + environment.getProperty("jdbc.username")); System.out.println("数据库密码:" + environment.getProperty("jdbc.password")); System.out.println("------------------------------------------------"); } catch (Exception ex) { ex.printStackTrace(); } } }
|
@PropertySource注解加载properties文件
PropertySource注解的作用是加载指定的属性文件,配置属性如下
1
| @PropertySource(value= {"classpath:config/mail.properties"},ignoreResourceNotFound=false,encoding="UTF-8",name="mail.properties")
|
- 其中value是设置需要加载的属性文件,可以一次性加载多个(多个时以,分隔);
- encoding用于指定读取属性文件所使用的编码,我们通常使用的是UTF-8;
- ignoreResourceNotFound含义是当指定的配置文件不存在是否报错,默认是false;如这里配置的config/mail.properties,若在classpath路径下不存在时,则ignoreResourceNotFound为true的时候,程序不会报错,如果ignoreResourceNotFound为false的时候,程序直接报错。实际项目开发中,最好设置ignoreResourceNotFound为false,该参数默认值为false。
- name的值我们设置的是mail.properties。这个值在Springboot的环境中必须是唯一的,如果不设置,则值为:“class path resource [config/mail.properties]“。
1 2 3 4 5 6 7 8 9 10 11
| @Component @ConfigurationProperties(prefix = "mail") @PropertySource(value = "classpath:config/mail.properties",encoding = "UTF-8") public class MailConfig { private String host; private String port; }
|
ConfigurationProperty和Value对比
| 描述 |
@ConfigurationProperties |
@Value |
| 底层框架 |
Spring Boot |
Spring |
| 使用位置 |
标注在 JavaBean 的类名上 |
标注在 JavaBean 的属性上 |
| 功能不同 |
用于批量绑定配置文件中的配置 |
只能一个一个的指定需要绑定的配置 |
| 需要setXX()方法 |
需要 |
有没有均可 |
| 复杂类型属性注入 |
支持所有类型数据的封装,例如 Map、List、Set、以及对象等; |
不支持复杂类型,只支持基本数据类型的封装,例如字符串、布尔值、整数等类型。 |
| 松散绑定 |
支持 例如实体类 Person 中有一个属性为 firstName,那么配置文件中的属性名支持以下写法: person.firstName person.first-name person.first_name PERSON_FIRST_NAME |
不支持 |
| SpEl支持 即${xxx}的EL表达式 |
不支持 |
支持,例 @Value(“${user.id}”) private String id; @Value(“${user.name}”) private String name; |
| 应用场景 |
若专门编写了一个 JavaBean 来和配置文件进行映射,则建议使用 @ConfigurationProperties 注解。 |
若只是获取配置文件中的某项值,则推荐使用 @Value 注解; |