配置文件是一种文本文件,通常用于存储程序的参数和设置。它包含了程序运行所需的各种选项和配置信息,例如界面风格、服务器连接信息、默认语言等。这些信息可以通过键值对的形式表示,也可以使用特定的语法和结构描述更复杂的配置信息。
配置文件通常由程序在启动时读取和解析,以自定义程序的行为。例如,在网站开发中,网站的配置文件通常包含了数据库连接信息、安全性设置、日志记录等重要信息。在操作系统中,配置文件则可以用于指定各种系统参数,如网络连接、设备驱动程序等。
配置文件的格式和内容因程序而异,常见的配置文件格式包括INI文件、XML文件、JSON文件等。INI文件是最早的配置文件格式之一,它使用简单的键值对语法来存储配置信息。XML和JSON文件则更加灵活和可扩展,可以描述更复杂的配置信息。
除了使用传统的文本编辑器手动编写配置文件外,现在也有许多工具可以帮助用户轻松地编辑和管理配置文件。例如,一些应用程序具有自己的配置文件编辑器,用户可以通过界面来直观地编辑配置信息。另外,一些配置管理工具则可以帮助用户自动化地管理和维护配置文件,例如版本控制、备份和恢复等。
SpringBoot⽀持并定义了配置⽂件的格式,也在另⼀个层⾯达到了规范其他框架集成到SpringBoot的⽬的。
很多项⽬或者框架的配置信息也放在配置⽂件中,⽐如:
每个 Spring 项目都内置了一个 Tomcat 服务器,而 Tomcat 默认使用的端口是 8080,如果 8080 端口被占用或者多个 Spring 项目同时启动的话,就会出现某些程序无法正常启动的情况,所以这时候就可以使用 Spring 的配置文件修改启动的端口。
不仅如此,在日常生活中我们很多时候都会和数据库打交道,而每个人甚至一个人的不同机器上的数据库用户名、密码和 IP 地址都是有区别的,那么当这个项目交给别人的时候就需要在 Spring 配置文件中修改相关的配置。
不仅如此,一些公共的属性以及会根据情况而改变的属性都可以放在这个 Spring 配置文件中,通过使用 Spring 配置文件可以帮助我们解决很多的问题。
我们先通过一个简单的例子来了解配置文件的作用。
我们创建 SpringBoot 项目的时候,会自动生成一个 application.properties
文件,这就是默认的 SpringBoot 配置文件,我们在这个配置文件中修改启动端口号看看结果。
server.port=9090
这里可以看到启动端口号修改成功了。
如果我们想要访问这个项目就不能使用 127.0.0.1:8080
了,而要使用 127.0.0.1:9090
地址了。
SpringBoot 的配置文件有三种形式:
yml 是 yaml 的缩写,两个使用方式是相同的。并且这两个配置文件还是生活中使用频率最高的。
当应⽤程序启动时,SpringBoot会⾃动从classpath路径找到并加载
application.properties 和 application.yaml 或者 application.yml ⽂件,当然也可以使用 spring.config.name
指定文件路径和名称。
那么 properties 配置文件和 yml 配置文件有什么区别呢?区别主要体现在语法和使用场景上。properties 配置格式出现的比较早,而 yml 配置格式出现的则比较晚,并且在语法上,yml 配置格式相较于 properties 配置格式来说更加的简介,并且很重要的是:properties 配置文件中如果出现中文的话出现乱码的几率非常大,而 yml 配置格式则对中文的支持度是比较高的。存在两种配置格式,可以一定程度上降低程序员的学习成本。
properties 配置⽂件是最早期的配置⽂件格式,也是创建 SpringBoot 项⽬默认的配置⽂件。
properties 配置格式是以键值对的形式存在的,key 和 value 之间通过“=”连接。并且 key 和 value 之间可以存在多个空格。
# 配置启动端口号
server.port=9090
# 配置数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?charEncoding=utf8&userSSL=false
spring.datasource.name=root
spring.datasource.password=123456
配置文件中使用 #
添加注释信息。
在项目中,如果想要主动读取配置文件中的信息的话,可以使用 @Value
注解来实现。
mykey=zhangsan
package com.example.springconfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PropertiesController {
@Value("mykey")
private String key;
@RequestMapping("/getkey")
public String getKey() {
return "获取到key:" + key;
}
}
这是为什么呢?我们的 mykey 不是 zhangsan 吗?为什么获取到的是 mykey 呢?
这是因为 Spring 将@Value
中的 “mykey” 当作了 value 赋值给了 key,那么我们该如何才能获取到 key mykey 中的 value 值呢?
要想获取到 @Value
key 中的 value 值,需要使用 ${}
来获取到这里面的 key 的 value 值。
@Value("${mykey}")
为什么说 properties 配置格式对中文不是很友好呢?我们来看看:
mykey=张三
为什么就肯定说是 properties 配置文件的问题而不是我们前端接收到响应之后出现的问题呢?我们打断点看看。
这里我们读取到 mykey 的时候就是乱码,而是我的 idea 也是默认是 UTF-8 格式,是支持中文的,所以说 properties 配置文件中尽量不要出现中文。
不仅如此,通过观察 properties 配置文件中的信息,我们会发现里面的内容是比较冗余的。
以上只是 properties 的两个显著的缺点。
yml 是 YAML 的缩写,它的全称 Yet Another Markup Language 翻译成中⽂就是“另⼀种标记语⾔。光看 yml 的翻译就可以看出来 yml 的理想是非常远的“语言”。我们先来看看 yml 配置文件的基本语法。
yml 配置文件对于语法要求是非常严格的,他虽然也是以键值对的形式存在的,但是 key 和 value 之间必须以 冒号 + 空格 相连接,这个空格是不能省略的。
如果配置成功,那么属性就会有高亮提示。
这种灰色,就说明该属性没有配置成功,也就是语法存在问题。
空格可以有多个。
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&userSSL=false
username: root
password: 123456
这种 yml 配置方式显示出了层级关系并且节省了很多代码:url、username和password属性属于datasource,而 datasource 则属于 spring。
yml 的使用不止有这些,还有其他更厉害的用法。
前面 properties 配置格式差不多所有的配置都是字符串类型,而在 yml 配置格式中还存在布尔类型、整数类型、浮点数类型以及Null类型。
# 字符串
string.value: hello
# 布尔类型
boolean.value: true
boolean.value1: false
# 整数类型
int.value: 10
# 浮点数
float.value: 3.14159
# Null ~ 代表null
null.value: ~
那么 yml 配置文件的属性如何读取呢?这些基本的数据类型是和 properties 配置格式是一样的,都是使用 @Value
注解来获取到指定的配置。
package com.example.springconfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PropertiesController {
@Value("${string.value}")
private String stringValue;
@Value("${boolean.value}")
private boolean flg1;
@Value("${boolean.value1}")
private boolean flg2;
@Value("${int.value}")
private int intValue;
@Value("${float.value}")
private float floatValue;
@Value("${null.value}")
private String nullValue;
@RequestMapping("/getkey")
public String getKey() {
return stringValue + " | " + flg1 + " | " + flg2 + " | "
+ intValue + " | " + floatValue + " | " + nullValue;
}
}
值得注意的是,在 yml 配置格式中,字符串的表现形式有三种,一种是不加引号、一种是加单引号、还有一种就是加双引号,与 properties 配置格式不同,因为 properties 配置格式都是字符串类型,所以从等号后面的第一个非空格字符开始就会被当成是字符串。
properties 配置格式
mykey1=abcde
mykey2='abcde'
mykey3="abcde"
@RestController
public class PropertiesController {
@Value("${mykey1}")
private String mykey1;
@Value("${mykey2}")
private String mykey2;
@Value("${mykey3}")
private String mykey3;
@RequestMapping("/getkey")
public String getKey() {
return mykey1 + " | " + mykey2 + " | " + mykey3;
}
}
string1: abcde
string2: 'abcde'
string3: "abced"
@RestController
public class YmlController {
@Value("${string1}")
private String string1;
@Value("${string2}")
private String string2;
@Value("${string3}")
private String string3;
@RequestMapping("/getymlkey")
public String getKey() {
return string1 + " | " + string2 + " | " + string3;
}
}
根据输出的内容可以看到,yml 中表示字符串的方式有三种,但是这三种方式又有一些区别。
string1: abc \n de
string2: 'abc \n de'
string3: "abc \n ed"
@RestController
public class YmlController {
@Value("${string1}")
private String string1;
@Value("${string2}")
private String string2;
@Value("${string3}")
private String string3;
@RequestMapping("/getymlkey")
public String getKey() {
System.out.println(string1);
System.out.println(string2);
System.out.println(string3);
return string1 + " | " + string2 + " | " + string3;
}
}
可以看到没有引号和单引号的用法基本上是一样的,但是双引号就会有区别,没有引号和单引号会将字符串中的一些特殊符号进行转义,使之呈现出跟字符串里面一样的内容,而双引号则不会进行转义。
yml 中不仅能配置一些基本的数据类型,还可以配置对象。啊?我没听错吧?yml 配置格式还能配置对象?没错,你没听错,我们 yml 就是这么厉害。那么在 yml 中如何配置对象呢?
student:
id: 123
name: zhangsan
age: 18
类似上面的配置格式就是 yml 配置对象,当然也可以使用行内写法(跟上面的写法作用是一致的)。
student1: {id: 234, name: lisi, age: 20}
那么如何取出配置的对象呢?这时候就不能使用 @Value
注解了,需要使用 ConfigurationProperties
注解,并且取出也需要借助类来读取。
package com.example.springconfiguration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
private int id;
private String name;
private int age;
}
仅仅只是通过类来读取也是不行的,还需要保证类中的属性名称和 yml 配置文件中的对象的属性名称一致,并且类中为这些属性提供了 getter 和 setter 方法。
这是 ConfigurationProperties
注解的参数,如果不指定参数的名称的话,默认就是value/prefix。
package com.example.springconfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class StudentController {
@Autowired
private Student student;
@RequestMapping("/readStudent")
public String readStudent() {
return student.toString();
}
}
yml 配置文件还可以配置集合。
dbtypes:
name:
- mysql
- sqlserver
- db2
读取 yml 配置文件中的集合同样是依赖 ConfigurationProperties
注解和类以及类中的 getter 和 setter 方法。
package com.example.springconfiguration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "dbtypes")
@Data
public class ListConfig {
private List<String> name;
}
package com.example.springconfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ListController {
@Autowired
private ListConfig listConfig;
@RequestMapping("/readList")
public String readList() {
return listConfig.toString();
}
}
yml 配置格式还可以配置 Map 类型的属性。
maptypes:
map:
k1: China
k2: America
k3: Japanese
行内写法:
maptypes2: {map: {k1: China, k2: America, k3: Japanese}}
读取 Map 类型配置也是依赖 ConfigurationProperties
注解和类以及类中的 getter 和 setter 方法。
package com.example.springconfiguration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "maptypes")
@Data
public class MapConfig {
private Map<String, String> map;
}
package com.example.springconfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MapController {
@Autowired
private MapConfig mapConfig;
@RequestMapping("/readMap")
public String readMap() {
return mapConfig.toString();
}
}
有可能我们一个项目中针对不同的情况会有不同的配置,那么我们是否要每到一个新环境就将另一个配置文件中的内容复制到当前使用的配置文件中吗?其实没必要,一个 Spring 项目中允许存在多个配置文件,并且我们可以指定使用哪个配置文件。
但是需要注意的是,spring 中的配置文件必须以 application-xxx.yml
格式命名。比如 application-dev.yml
和 application-prod.yml
,如果需要切换的话,只需要在 application.yml
配置文件中加入
spring:
profiles:
active: dev # application-xxx.yml 这里填 - 后面的字符
假设我们这里使用 application-dev.yml
配置文件。
优点:
缺点: