02-SpringBoot配置文件
一、配置文件的使用
SpringBoot使用一个全局的配置文件(核心配置文件),配置文件名在约定的情况下是固定的;配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;
application.properties
application.yml
二、两种配置文件的格式
在springboot框架中,resource文件夹里可以存放配置的文件有两种:properties和yml。
1、application.properties的用法:扁平的k/v格式。(key/value)
server.port=8081 server.servlet.context-path=/tuling2、application.yml的用法:树型结构 可读性更强 值前面一定要有空格
server: port: 8088 servlet: context-path: /tuling三、配置文件的加载顺序
2.3.x:官方没有具体说明,实测以properties为准
2.4.0:如果指定了多个位置,则后一个位置可以覆盖前一个位置的值。
2.4.4:建议整个应用程序使用一种格式,如果您的配置文件的格式.properties和.yml都位于同一位置,则以properties优先级为准。
3.1.5:以.properties为准。
四、其它约定配置文件加载顺序
springboot启动还会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件:
低:
1、classpath的根目录下的
2、classpath的根config/
3、项目根目录
如果当前项目是继承/耦合 关系maven项目的话,项目根目录=父maven项目的根目录
4、项目根目录/comfig
5、直接子目录/config
高
优先级由低到高,高优先级的配置会覆盖低优先级的配置;互补配置;
五、profile配置文件加载
Profile的意思是配置,对于应用程序来说,不同的环境要不同的配置。
SpringBoot框架提供了多profile的管理功能,我们可以使用profile功能来区分不同环境的配置。
1.Spring官方给出的语法规则是application-{properties}.properties(.yaml/.yml)。
2.如果需要创建自定义的properties文件时,可以用application-xxx-properties的命名方式。
六、配置文件值注入
1.@vaule
package com.example.hello.beans; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Map; //可以通过@Value + SPEL表达式来直接绑定springbooot配置文件中的值 @Component public class User { @Value("${user.username}") private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<String> getHobbies() { return hobbies; } public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; } public Map<Integer, String> getGirlFriend() { return girlFriend; } public void setGirlFriend(Map<Integer, String> girlFriend) { this.girlFriend = girlFriend; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } private Integer age; private Date birthday; private List<String> hobbies; private Map<Integer,String> girlFriend; private Address address; @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + ", birthday=" + birthday + ", hobbies=" + hobbies + ", girlFriend=" + girlFriend + ", address=" + address + '}'; } }package com.example.hello.beans; import org.springframework.stereotype.Component; @Component public class Address { public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } private Integer id; private String desc; }application.properties
user.username=123 server.port=8080运行结果:
2.@ConfigurationProperties(prefix="user")
package com.example.hello.beans; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Map; @Component @ConfigurationProperties(prefix ="user") public class User { // @Value("${user.username}") private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<String> getHobbies() { return hobbies; } public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; } public Map<Integer, String> getGirlFriend() { return girlFriend; } public void setGirlFriend(Map<Integer, String> girlFriend) { this.girlFriend = girlFriend; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } // @Value("${user.age}") private Integer age; @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday; private List<String> hobbies; private Map<Integer,String> girlFriend; private Address address; @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + ", birthday=" + birthday + ", hobbies=" + hobbies + ", girlFriend=" + girlFriend + ", address=" + address + '}'; } }user: username: 徐庶 age: 25 birthday: 1999-01-01 hobbies: - 读书 - 游泳 - 编程 girlFriend: 1: 貂蝉 2: 小乔 address: id: 1 desc: 河南省郑州市 server: port: 8080运行结果:
User{username='徐庶', age=25, birthday=Fri Jan 01 00:00:00 CST 1999, hobbies=[读书, 游泳, 编程], girlFriend={1=貂蝉, 2=小乔}, address=Address{id=1, desc='河南省郑州市'}}松散绑定:
user: USERNAME: 徐庶 user: userName: 徐庶 user: user-name: 徐庶 user: user_name: 徐庶 以上四种命名是可以自动绑定bean属性 User.username3.@ConfigurationProperties对比@Value 获取值
JSR303数据校验,二者都支持
4.配置文件占位符
@ConfigurationProperties不支持SPEL表达式,只支持两种占位符。
1.对属性值的引用占位符
2.对属性随机值的引用
补:SPEL表达式
| 分类 | 核心内容 | 示例表达式 | 说明与用途 |
|---|---|---|---|
| 表达式的样子 | 写在#{...}里 | #{3 + 5} | 这是 SpEL 的标准语法,一眼就能认出来,区别于属性占位符${...}(用于读取外部配置文件)。 |
| 支持的数据类型 | 字面量、数字、布尔、字符串、集合等 | #{'Hello'}#{1 > 0}#{1,2,3} | 支持常见的 Java 数据类型,还可以直接写集合,比如 List 和 Map。 |
| 能做什么运算 | 算术、比较、逻辑、三元、正则匹配 | #{1 + 2 * 3}#{score >= 60}#{age > 18 ? '成人' : '未成年'} | 几乎覆盖了所有常见的运算逻辑,可以替代很多简单的 Java 判断代码。 |
| 如何访问数据 | 操作对象属性、调用方法、访问容器 Bean | #{user.name}#{user.getName()}#{@userService.findById(1)} | 这是 SpEL 最核心的能力,可以灵活地读取或调用程序中的任何对象。用@前缀就能直接拿到 Spring 容器里的 Bean。 |
| 特殊的变量 | 系统属性、方法参数、安全上下文等 | #{systemProperties['java.version']}#{#param1}#{authentication.name} | 内置了很多常用对象,让你能方便地获取环境信息或当前请求的上下文。参数用#参数名来引用。 |
| 处理空值 | 安全的导航操作符 | #{user?.address?.city ?: '未知'} | ?.会优雅地处理空指针,如果中间任何一个对象是null,就不会报错,直接返回null或指定的默认值。 |
| 主要应用场景 | 注解赋值、权限校验、条件化配置 | @Value("#{...}")@PreAuthorize("#{...}")@ConditionalOnExpression("...") | 这三个注解(见右侧)覆盖了 90% 以上的日常使用场景,让你的配置和代码变得非常灵活。 |
5.属性注入---数据校验
<!-- 数据校验--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'user' to com.example.hello.beans.User failed: Property: user.address Value: "null" Reason: 不能为null七、总结
自定义配置文件绑定值
