SpringBoot 项目中所有重要的数据都是在配置文件中配置的,比如∶
想象一下如果没有配置信息,那么 Spring Boot 项目就不能连接和操作数据库,甚至是不能保存可以用于排查问题的关键日志,所以配置文件的作用是非常重要的。
配置文件中的配置类型有两类,一类是系统配置项,这种配置的格式都是固定的,是给系统(框架)使用的;另一种是用户自定义配置,用户可以随意地规定配置项的格式,又用户自行去设置和读取。
SpringBoot 项目配置文件有两种,一种是项目创建默认自带的的properties文件,还有一种比较新的yml文件(需要自己添加)。
配置文件是存在于resources目录下的,对于 SpringBoot 项目默认的配置文件,配置文件名必须是application,即application.properties或application.yml文件,如果配置文件名不为application那就不能够被识别加载。
properties是可以和yml⼀起存在于⼀个项⽬当中的,yml文件相比于properties文件做了一些优化,如yml文件天然支持中文字符,而properties文件默认是不支持中文字符的,如果不进行字符配置,输入中文字符就会有乱码现象。
当application.properties和application.yml两个文件共存时, 虽然两个文件中的配置都会被加载,但如果这两个配置⽂件中出现了同样的配置(比如 properties 和 yml 中都配置了“server.port” ), 那么这个时候会以properties中的配置为主,也就是.properties配置⽂件的优先级最⾼。
虽然理论上来讲 .properties 可以和 .yml 共存,但实际的业务当中,我们通常会采取⼀种统⼀的配置⽂件格式,这样可以更好的维护(降低故障率)。
properties 配置文件是最早期的配置文件格式,也是创建 Spring Boot 项目默认的配置文件。
🎯基本语法:
properties 是以键值的形式配置的,key 和 value 之间是以“=”连接的, 使⽤“#”来添加注释信息。
# key与=与value之间不要加空格 key=value
比如,设置端口号,我们可以使用配置项server.port来设置端口:
server.port=8088
配置修改完毕后,启动程序,就可以看到端口号已经设置成配置文件中所设置的端口号了。
还有比如设置数据库,配置项如下:
# 配置数据库 URL spring.datasource.url="jdbc:mysql://127.0.0.1:3306/tr?characterEncoding=utf8&useSSL=false" # 配置数据库 username spring.datasource.name="root" # 配置数据库 password spring.datasource.password="111111" # 设置驱动 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
有关更多系统的配置,可以去看看官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties
除了设置配置文件的信息除了系统的配置,我们还可以自定义配置,比如:
# 用户自定义配置 custom.name=zhangsan custom.id=666
🎯此时要读取配置文件中的信息,我们可以使用@Value注解来实现,规则如下:
// 要注意${}不能省略 @Value("${配置信息key}") private String name;
示例代码:
package com.example.springboot.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @ResponseBody public class TestController2 { // 自定义配置和系统配置都可以读取 @Value("${custom.name}") private String name; @Value("${custom.id}") private String id; @Value("${server.port}") private String port; @RequestMapping("/coustom") public String sayHi() { return "name : " + name + " " + "id : " + id + " " + "port : " + port; } }
浏览器访问结果:
优点:
缺点:
yml 是 YMAL(Yet Another Markup language)的缩写,翻译为另一种标记语言。
🎯基本语法:
yml 是树型结构配置文件,特别需要注意的是 key 和 value 之间需要使用英文冒号加空格,空格一定是不能省略的。
# :后面空格一定不能省 key: value
此时,将上面的propertise转换成yml格式看一下。
# 配置端口 server: port: 8088 # 配置数据库 spring: datasource: url: "jdbc:mysql://127.0.0.1:3306/tr?characterEncoding=utf8&useSSL=false" username: "root" password: "111111" # 自定义配置信息 custom: name: zhangsan id: 666
这里读取 yml 配置文件的方式和 properties 配置文件是一样的,就不再演示了。
我们尝试将配置文件中的配置信息设置成如下字样:
string: str1: Hello \n Spring Boot. str2: 'Hello \n Spring Boot.' str3: "Hello \n Spring Boot."
我们将这些配置信息注入到一个类,我们尝试来读取它们,这个代码 @Controller 在 Spring Boot 启动时候会把 YmlString 对象注⼊到框架中,当注⼊到框架中时会执⾏ @PostConstruct 初始化方法,就是此时读到的配置信息。
@Controller public class YmlString { @Value("${string.str1}") private String str1; @Value("${string.str2}") private String str2; @Value("${string.str3}") private String str3; @PostConstruct public void postConstruct() { System.out.println("string.str1:" + str1); System.out.println("string.str2:" + str2); System.out.println("string.str3:" + str3); } }
控制台输出结果:
这就说明,被双引号包裹的值,是按照原语义执行的,而被单引号包裹值(特殊字符)会发生转义,像上面的例子就是\n转义成了\\n,所以就输出了\n,最终就只是一个普通的字符串。
至于不加双引号的输出结果是因为 yml 中字符串默认是不加引号的,就直接输出了。
格式如下:
# 字符串 string.value: Hello # 布尔值,true或false boolean.value: true boolean.value1: false # 整数 int.value: 10 int.value1: 0b1010_0111_0100_1010_1110 # ⼆进制 # 浮点数 float.value: 3.14159 float.value1: 314159e-5 # 科学计数法 # Null,~代表null null.value: ~
使用:
package com.example.springboot.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class TestController3 { @Value("${string.value}") private String str; @Value("${boolean.value}") private boolean bool; @Value("${float.value}") private float flo; @Value("${null.value}") private Integer nul; @PostConstruct public void postConsrtuct() { System.out.println("str: " + str); System.out.println("bool: " + bool); System.out.println("flo: " + flo); System.out.println("nul: " + nul); } }
运行结果:
对于 ym l配置文件,还能进行对象的配置,如设置一个Student对象:
方式1:
student: id: 1 name: 张三 age: 18
方式2:
student: {id: 1,name: 张三,age: 18}
此时从配置文件读取自定义的对象,就不可以使用 @Value 注解来读取了,需要使用@ConfigurationProperties注解来进行对象的读取,并且对应的类必须有getter和setter方法。
🍂示例:
学生类:
我们这里就不自己写getter和setter方法了,我们使用 Lombok 框架中的 @Data 注解即可,其中就包含了get,set 和 toString,免去了手动创建的步骤了。
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @ConfigurationProperties(prefix = "student") @Component public class Student { private int id; private String name; private int age; }
使用类:
package com.example.springboot.controller; import com.example.springboot.model.Student; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import javax.annotation.PostConstruct; @Controller public class ConfigController { @Autowired private Student student; @PostConstruct public void postConsrtuct() { System.out.println(student); } }
运行结果:
yml 还能配置集合
🎯比如配置 list 集合,配置方式如下:
方式1:
dbtypes: name: - mysql - sqlserver - db2
方式2(推荐):
dbtypes: {name: [mysql, sqlserver, db2]}
获取与对象的获取方式一模一样,只是现在需要类里面的一个属性为集合对象。
获取示例:
与配置文件对应的对象。
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.List; @Data @ConfigurationProperties(prefix = "dbtypes") @Component public class ConfigList { private Listname; }
使用类:
package com.example.springboot.controller; import com.example.springboot.model.ConfigList; import org.springframework.stereotype.Controller; import javax.annotation.PostConstruct; import javax.annotation.Resource; @Controller public class ConfigController { @Resource private ConfigList configList; @PostConstruct public void postConstruct() { System.out.println(configList.getName()); } }
运行结果:
🎯再比如配置 map 集合,配置方式如下:
方式1:
tes: map: 1: 张三 2: 李四
方式2:
tes: maps: {1: 张三,2: 李四}
获取示例:
与配置文件对应的对象:
package com.example.springboot.model; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Map; @Data @ConfigurationProperties(prefix = "tes") @Component public class ConfigMap { private Mapmap; }
使用类:
package com.example.springboot.controller; import com.example.springboot.model.ConfigMap; import org.springframework.stereotype.Controller; import javax.annotation.PostConstruct; import javax.annotation.Resource; @Controller public class ConfigController2 { @Resource private ConfigMap configMap; @PostConstruct public void postConstruct() { System.out.println(configMap.toString()); } }
运行结果:
在日常开发中,通常会使用至少三个不同的环境:开发环境(dev)、测试环境(test)和生产环境(prod);每个环境的配置都不相同,包括数据库、端口、IP 地址等信息;那么如何区分这些环境,如何打包呢?
Spring Boot 中提供了很好的多环境整合支持,可以在打包和运行时自由切换不同的环境。
为了方便管理不同环境的配置,可以将它们放在不同的配置文件中,此时我们就需要创建不同环境的配置文件了,例如application-dev.properties、application-test.properties和application-prod.properties。
需要注意的是,配置文件的命名必须遵循application-name.properties或application-name.yml的格式,其中的name可以自定义,用于区分不同的环境。
因此,在整个项目中,需要有四个配置文件,包括application.properties(主配置文件,是必须存在的)和三个不同环境的配置文件。
此时创建了各个环境的配置文件条件下,还需要告诉 SpringBoot 你要运行哪个环境,主要有两种指定方式。
🎯方式1:在主配置文件中指定
可以在主配置文件(application.properties或者application.yml)中指定,内容如下:
# 指定运行环境为测试环境(application.properties) spring.profiles.active=test # 指定运行环境为生产环境(application.xml) spring: profiles: active: pord
此时,SpringBoot 首先默认会加载application.properties文件,而这个的文件配置又告诉 SpringBoot 去找指定环境的配置文件。
🎯方式2:运行 jar 的时候指定
SpringBoot 内置的环境切换能够在运行Jar包的时候指定环境,命令如下:
java -jar xxx.jar --spring.profiles.active=test