在SpringBoot框架中,提供了两种不同格式的配置文件,一个是properties,另一个是yaml(也叫做yml)。虽然properties文件比较常见,但是相对于properties而言,yaml更加简洁明了,而且使用的场景也更多,很多开源项目都是使用 yaml进行配置。除了简洁,yaml还有另外一个特点,就是yaml中的数据是有序的,properties中的数据是无序的,在一些需要路径匹配的配置中,顺序就显得尤为重要(例如我们在SpringCloud-Zuul中的配置),此时我们一般采用yaml。
一、properties配置说明
1.1properties文件位置说明
首先,当我们创建一个SpringBoot工程时,默认resources目录下就有一个application.properties文件,可以在application.properties文件中进行项目配置,但是这个文件并非唯一的配置文件,在SpringBoot中,一共有4个地方可以存放application.properties文件。
当前项目根目录下的config目录下;
当前项目的根目录下;
resources目录下的config目录下;
resources目录下;
按如上顺序,四个配置文件的优先级依次降低。如下:
这四个位置是默认位置,即SpringBoot启动,默认会从这四个位置按顺序去查找相关属性并加载。但是,这也不是绝对的,我们也可以在项目启动时自定义配置文件位置。
例如,在resources目录下创建一个javaboy目录,目录中存放一个application.properties文件,那么正常情况下,当我们启动SpringBoot项目时,这个配置文件是不会被自动加载的。
我们可以通过spring.config.location属性来手动的指定配置文件位置,指定完成后,系统就会自动去指定目录下查找application.properties文件。
此时,启动项目就会发现,项目以classpath:/javaboy/application.propertie配置文件启动。这是在开发工具中配置了启动位置,如果项目已经打包成 jar ,在启动命令中加入位置参数即可:
java -jar properties-0.0.1-SNAPSHOT.jar -- spring.config.location=classpath:/javaboy/
1.2properties文件名说明
对于application.properties而言,它不一定非要叫application,但是项目默认是去加载名为application的配置文件,如果我们的配置文件不叫application,也是可以的,但是,需要明确指定配置文件的文件名。方式和指定路径一致,只不过此时的key是 spring.config.name 。
首先我们在resources目录下创建一个app.properties文件,然后在 IDEA 中指定。配置文件的文件名:
指定完配置文件名之后,再次启动项目,此时系统会自动去默认的四个位置下面分别查找名为app.properties的配置文件。当然,允许自定义文件名的配置文件不放在四个默认位置,而是放在自定义目录下,此时就需要明确指定 spring.config.location 。
注意:配置文件位置和文件名称可以同时自定义。
1.3properties文件配置内容解析
普通属性注入
由于SpringBoot源自Spring框架,所以Spring中存在的属性注入,在SpringBoot中一样也存在。由于SpringBoot中,默认会自动加载application.properties文件, 所以简单的属性注入可以直接在这个配置文件中写。
例如,现在定义一个 Book 类:
public class Book {
private Long id;
private String name;
private String author;
//省略 getter/setter
}
然后,在application.properties文件中定义属性:
book.name=三国演义
book.author=罗贯中
book.id=1
按照传统的方式(Spring中的方式),可以直接通过 @Value 注解将这些属性注入到 Book 对象中:
@Component
public class Book {
@Value("${book.id}")
private Long id;
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
//省略 getter/setter
}
注意 :
Book对象本身也要交给Spring容器去管理,如果Book没有交给Spring容器,那么Book中的属性也无法从Spring容器中获取到值。配置完成后,在Controller或者单元测试中注入Book对象,启动项目,就可以看到属性已经注入到对象中了。
一般来说,我们在application.properties文件中主要存放系统配置,这种自定义配置不建议放在该文件中,可以自定义properties文件来存在自定义配置。
例如在 resources 目录下,自定义book.properties文件,内容如下:
book.name=三国演义
book.author=罗贯中
book.id=1
此时,项目启动并不会自动的加载该配置文件,如果是在 XML 配置中,可以通过如下方式引用该properties文件:
<context:property-placeholder location="classpath:book.properties"/>
如果是在Java配置中,可以通过@PropertySource来引入配置:
@Component
@PropertySource("classpath:book.properties")
public class Book {
@Value("${book.id}")
private Long id;
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
//getter/setter
}
这样,当项目启动时,就会自动加载book.properties文件。
类型安全的属性注入
SpringBoot引入了类型安全的属性注入,如果采用Spring中的配置方式,当配置的属性非常多的时候,工作量就很大了,而且容易出错。使用类型安全的属性注入,可以有效的解决这个问题。
@Component
@PropertySource("classpath:book.properties")
@ConfigurationProperties(prefix = "book")
public class Book {
private Long id;
private String name;
private String author;
//省略 getter/setter
}
这里,主要是引入@ConfigurationProperties(prefix = "book") 注解,并且配置了属性的前缀,此时会自动将Spring容器中对应的数据注入到对象对应的属性中,就不用通过@Value注解挨个注入了,减少工作量并且避免出错。
二、yml配置说明
1.1yml文件位置说明
首先application.yaml在SpringBoot中可以写在四个不同的位置,分别是如下位置:
项目根目录下的config目录中;
项目根目录下;
classpath下的config目录中;
classpath目录下;
四个位置中的application.yaml文件的优先级按照上面列出的顺序依次降低。如果有同一个属性在四个文件中都出现了,以优先级高的为准。
那么application.yaml是不是必须叫application.yaml这个名字呢?
当然不是必须的。开发者可以自己定义yaml名字,自己定义的话,需要在项目启动时指定配置文件的名字,像下面这样:
当然这是在IntelliJ IDEA中直接配置的,如果项目已经打成 jar 包了,则在项目启动时 加入如下参数:
java -jar myproject.jar --spring.config.name=app
这样配置之后,在项目启动时,就会按照上面所说的四个位置按顺序去查找一个名为app.yaml的文件。
当然这四个位置也不是一成不变的,也可以自己定义,有两种方式:
一个是使用spring.config.location属性;
另一个是使用spring.config.additional-location属性;
在第一个属性中,表示自己重新定义配置文件的位置,项目启动时就按照定义的位置去查找配置文件,这种定义方式会覆盖掉默 认的四个位置。
也可以使用第二种方式,第二种方式则表示在四个位置的基础上,再添加几个位置,新添加的位置的优先级大于原本的位置。
配置方式如下:
注意:这里配置文件位置时,值一定要以 / 结尾。
1.2yml文件配置内容解析
数组注入
yaml也支持数组注入,例如:
my:
servers:
- dev.example.com
- another.example.com
这段数据可以绑定到一个带Bean的数组中:
@ConfigurationProperties(prefix="my")
@Component
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
项目启动后,配置中的数组会自动存储到servers集合中。当然,yaml不仅可以存储这种简单数据,也可以在集合中存储对象。
例如下面这种:
redis:
redisConfigs:
- host: 192.168.200.129
port: 6379
- host: 192.168.200.129
port: 6380
这个可以被注入到如下类中:
@Component
@ConfigurationProperties(prefix = "redis")
public class RedisCluster {
private List<SingleRedisConfig> redisConfigs;
//省略 getter/setter
}
三、properties和yml文件加载优先级说明
上面的内容介绍中,有说到配置文件加载的优先级问题,下面就通过源码来看下配置文件具体的加载顺序。我们知道springboot项目的入口在其启动类中,主要就是run方法配合启动类上相关注解来完成。
1.1properties和yml加载顺序优先级说明
首先基于自动配置,我们知道springboot项目启动时,会优先加载springboot核心jar包下META-INF文件夹下的spring.factories文件。而在spring.factories文件中首先配置了配置文件的加载顺序,我们可以看到配置资源的加载是properties文件优先于yml文件。
其中PropertiesPropertySourceLoader类中定义了扩展名为properties、xml的文件。
而YamlPropertySourceLoader类中定义了扩展名为yml、yaml的文件。
对于同一位置上,properties文件的优先级高于yml。
上述说明了properteis和yml文件的加载顺序优先级之后,接下来咱们就重点来看下对于不同位置的配置文件,它们的加载顺序是怎么样的。
1.2不同位置配置文件加载顺序优先级说明
对于不同位置的配置文件,它们的加载顺序其实springboot的ConfigFileApplicationListener类中是有说明的。
该类已在spring.factories中配置,当springboot项目启动时就会加载。而在ConfigFileApplicationListener类中,则定义了配置文件加载顺序的方法。
在ConfigFileApplicationListener类中,我们重点看一个方法getSearchLocations方法。
结论:
大家可以发现上述截图中返回Set类型的locations对象中,对应索引位置的值和ConfigFileApplicationListener类上注释中说明的不同位置的配置文件的加载顺序是一致的。
1.3bootstrap、application配置文件说明
其实在springboot框架中,还有一个配置文件,它的前缀是指定好的,叫做bootstrap。
它分为bootstrap.yml和bootstrap.properties。在我们做项目时,如果我们要使用bootstrap,那么建议我们至少统一后缀后在使用。
比如:bootstrap.yml、application.yml
或者 bootstrap.properties、application.properties。
其中bootstrap.yml或者bootstrap.properties配置文件主要在程序引导时执行,它的加载应用于更加早期配置信息读取。
而application.yml或者application.properties配置文件是应用程序特有配置信息,主要用来配置模块中需使用的公共参数。
总结
application.properties是SpringBoot中配置的一个重要载体,很多组件的属性都可以在这里定制。
它的用法和yaml 比较类似。关于yaml配置,它的文件位置和文件名是和properties一样的,我们只需要将properties文件的后缀名称由.properties改为.yml或者.yaml即可。在使用上properties文件是采用k=v格式来配置,yaml文件则是有严格的语法格式规则,我们按照规则去配置即可。