SpringBoot系列(9):SpringBoot配置文件详解

目录

前言

1、自动化配置

2、外部化配置

2.1 配置文件

2.2 自定义参数

2.3 参数引用

2.4 使用随机数

2.5 命令行参数

2.6 多环境配置

2.7 加载顺序

前言

约定 > 配置 > 编码

Spring Boot 对于开发人员最大的好处在于可以对 Spring 应用进行自动配置。在SpringBoot项目中,很多时候需要用到一些配置的信息,这些信息可能在测试环境和生产环境下会有不同的配置,针对这种情况,项目所需属性就需要灵活设置,尽可能地不要将这些配置在代码中写死,最好就是写到配置文件中,以便后面根据实际业务需求灵活修正。

1、自动化配置

Spring Boot会根据应用中声明的第三方依赖来自动配置 Spring 框架,而不需要进行显式的声明。比如当声明了对 HSQLDB 的依赖时,Spring Boot 会自动配置成使用 HSQLDB 进行数据库操作。

Spring Boot 推荐采用基于Java 注解的配置方式,而不是传统的 XML。只需在主配置Java类引@EnableAutoConfiguration”注解就可以启用自动配置。当然,根据目前SpringBoot版本的迭代更新,在多数情况下,我们只需注入@SpringBootApplication这个注解即可替代。

而且,Spring Boot 的自动配置功能是没有侵入性的,只是作为一种基本的默认实现。开发人员可以通过定义其他bean来替代自动配置所提供的功能。比如当应用中定义了自己的数据源bean时,自动配置所提供的 HSQLDB 就不会生效。这给予了开发人员很大的灵活性。既可以快速的创建一个可以立即运行的原型应用,又可以不断的修改和调整以适应应用开发在不同阶段的需要。可能在应用最开始的时候,嵌入式的内存数据库(如 HSQLDB)就足够了,在后期则需要换成MySQL数据库。Spring Boot 使得这样的切换变得很简单。

2、外部化配置

在应用中管理配置并不是一个容易的任务,尤其是在应用需要部署到多个环境中时。通常会需要为每个环境提供一个对应的属性文件,用来配置各自的数据库连接信息、服务器信息和第三方服务账号等。

通常的应用部署会包含开发、测试和生产等若干个环境,不同的环境之间的配置存在覆盖关系。测试环境中的配置会覆盖开发环境,而生产环境中的配置会覆盖测试环境。Spring 框架本身提供了多种的方式来管理配置属性文件,Spring 3.1 之前可以使用 PropertyPlaceholderConfigurer。Spring 3.1 引入了新的环境(Environment)和概要信息(Profile)API,是一种更加灵活的处理不同环境和配置文件的方式。不过 Spring 这些配置管理方式的问题在于选择太多,让开发人员无所适从。Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性文件、YAML 文件、环境变量和命令行参数来定义优先级不同的配置值。

      Spring Boot 所提供的配置优先级顺序比较复杂。按照优先级从高到低的顺序,具体的列表如下所示。

命令行参数。
通过 System.getProperties() 获取的 Java 系统参数。
操作系统环境变量。
从 java:comp/env 得到的 JNDI 属性。
通过 RandomValuePropertySource 生成的“random.*”属性。
应用 Jar 文件之外的属性文件。
应用 Jar 文件内部的属性文件。
在应用配置 Java 类(包含“@Configuration”注解的 Java 类)中通过“@PropertySource”注解声明的属性文件。
通过“SpringApplication.setDefaultProperties”声明的默认属性。
        Spring Boot 的这个配置优先级看似复杂,其实是很合理的。比如命令行参数的优先级被设置为最高。这样的好处是可以在测试或生产环境中快速地修改配置参数值,而不需要重新打包和部署应用。

2.1 配置文件

举个栗子:搭建一个最基础的SpringBoot工程。

如上图所示,Spring Boot工程的基础结构包括四个部分(具体路径根据用户生成项目时填写的GroupId和ArtifactId有所差异)。

src/main/java:存放主要编码的区域。如上边栗子,SpringBootMavenApplication.java这个类就是工程的主程序入口类,可以通过直接运行该类来启动Spring Boot应用。
src/main/reources:存放默认配置的目录。 该目录存放应用级别配置文件----application.yml文件(看个人喜好,这个文件作用等同于application.peoperties文件,唯一区别在于语法格式的不同),用来存放应用的一些配置信息, 如应用名、服务端口、数据库链接等。如果在搭建工程初期就引入Web模块,maven工程会自动产生static目录与templates目录,前者用于存放静态资源, 如图片、css、JavaScript等;后者存放Web页面的模板文件, 可根据实际需要灵活产生或删除这两个目录。
src/test:单元测试目录。 生成的测试类通过JUnit 4实现, 可以直接用运行Spring Boot应用的测试。
pom.xml:SpringBoot项目级别的核心配置文件。这个pom.xml主要描述了项目的maven坐标,依赖关系,属性配置,开发者需要遵循的规则,缺陷管理系统,组织和licenses,maven插件配置以及其他所有项目相关因素。
Spring Boot的配置文件除了可以使用传统的 properties文件之外,还支持现在被广泛推荐使用的YAML文件。Spring Boot 的默认配置文件位置为:src/main/reources/application.yml。SpringBoot应用的配置内容都可以集中在该文件中, 根据pom.xml文件中引入的不同Starter模块,可以在application.yml文件内定义容器端口号、 数据库连接信息、 日志级别、MyBatis、redis等等各种配置信息。

比如, 我们需要自定义Web模块的服务端口号,可以在application.yml中添加如下内容来指定SpringBoot项目的应用配置信息。

#application-level config
#profiles active
server:
port: 8080
#log config
logging:
config: /HL/IdeaProjects/SpringBoot-Item/springboot-slf4j/src/main/resources/logback.xml
level:
com.hl.magic: error
关于YML文件定义,这里简单总结一下。

YAML (英语发音为l'j知回/,, 尾音类似camel骆驼)是 一个可读性高, 用来表达资籵序列的格式。

YAML参考了其他多种语言, 包括C语言、Python、Perl,并从XML、 电子邮件的数据格式(RFC 2822)中获得灵感。 Clark Evans在2001年首次发表了这种语言,Ingy dot Net与OrenBen寸q如也是这种语言的共同设计者。 目前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

YAML是 YAML 扣n't a Markup Lan伊1age (YAML 不是一种标记语言)的缩写。在开发这种语言时, YAML的意思其实是: Yet Another Markup Language (仍是一种标记语言),但为了强调这种语言以数据作为中心,而不是以标记语言为重点,而用反向缩略语重新命名。

YAML的语法和其他高阶语言类似, 并且可以简单地表达清单、 散列表、 标量等形态。它使用空白符号缩排和大量依赖外观的特色, 特别适合用来表达或编辑数据结构、各种设定文档、 文件大纲(例如, 许多电子邮件标题格式和 YAML 非常接近)。尽管它比较适合表达阶层式 (hierarchical model)的数据结构, 不过也有精致的语法可以表示关联性 (relational model)的资籵。 由于YAML 使用空白符号和分行未分隔资籵, 使得它特别适合用 grep / Python / Perl /Ruby操作。其让人最容易上手的特色是巧妙避开各种封闭符号,如引号、各种括号等, 这些符号在巢状结构时会变得复杂而难以辨认。——————维基百科

YAML 采用的配置格式不像 properties 的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示。 下面是一段 YAML 配置信息:

spring:
profiles:
active: dev
#MVC
mvc:
servlet:
load-on-startup: 1
上边的配置信息在application.properties文件中等同配置如下:

spring.profiles.active=dev
Spring.mvc.servlet.load-on-startup=1
 通过 YAML 的配置方式我们可以看到,配置信息利用阶梯化缩进的方式, 其结构更为清晰易读, 同时配置内容的字符量也得到显著减少。

除此之外,YAML 还可以在一个单个文件中通过使用 spring.profiles 属性来定义多个不同的环境配置。 例如下面的内容,在指定为test环境时,server.port 将使用8081端口;在 prod 环境中,server.port将使用8082端口;而在 dev环境中,server.port将使用8083端口;如果没有指定环境,server.port将使用默认的8080端口。

server:
port: 8080
---
spring:
profilea: test
server:
port: 8081
---
spring:
profilea: prod
server:
port: 8082
---
spring:
profilea: dev
server:
port: 8083
2.2 自定义参数

除了可以在 Spring Boot 的配置文件中设置各个Starter 模块中预定义的配置属性, 也可以在配置文件中定义一些我们需要的自定义属性。 针对application.yml文件和 application.properties文件中自定义参数,栗子。

【1】在 application.yml文件中定义如下:

book:
name: Spring Boot In Action
author: xiaoming
 【2】在application.properties文件中定义如下:

book.name=Spring Boot In Action
book.author=xiaoming
上边两种文件内的自定义参数,实际上是等效的。接下来,我们在应用中可以通过@Value注解来加载这些自定义的参数,如:

@Component
public class Book {

@Value("${book.name}")
private String name;

@Value("${book.author}")
private String author;

/**省略getter和setter方法*/
}
 @Value 注解加载属性值的时候可以支持两种表达式来进行配置, 如下所示。

• 一种是上面介绍的 PlaceHolder 方式,格式为${...},大括号内为 PlaceHolder。

• 另一种是使用SpEL 表达式 (Spring Expression Language), 格式为#{...}, 大括号内为 SpEL 表达式。

2.3 参数引用

对于参数引用的方式, 其主要区别在于application.yml文件和 application.properties文件中对于参数定义及引用方式。

【1】 application.yml文件

在 application.yml中的各个参数之间可以直接通过使用 PlaceHolder 的方式来进行引用 , 就像下面的设置:

book:
name: Spring Boot In Action
author: xiaoming
desc: ${book.name} is writing 《${book.name}》
book.desc 参数引用了上边中定义的book.name和book.author 属性, 最后该属性的值就是xiaoming is writing《Spring Boot In Action》。

【2】 application.properties文件

在 application.yml中的各个参数之间可以直接通过使用 PlaceHolder 的方式来进行引用 , 就像下面的设置:

book.name=Spring Boot In Action
book.author=xiaoming
book.des=${book.name} is writing 《${book.name}》
 book.desc 参数引用了上边中定义的book.name和book.author 属性, 最后该属性的值就是xiaoming is writing《Spring Boot In Action》。

2.4 使用随机数

在一些特殊情况下, 我们希望有些参数每次被加载的时候不 一个固定的值, 比如密钥、 服务端口等。 在 SpringBoot的属性配置文件中, 可以 通过 使用${random}配置来产生随机的int值、long值或者string字符串,这样我们就可以容易地通过配置随机生成属性,而不是在程序中通过编码来实现这些逻辑。

【1】 application.yml文件

${random}的配置方式主要有以下几种, 读者可作为参考使用。
#随机字符串
com:
didispace:
blog:
value: ${random.value}
#随机int
number: ${random.int}
#随机long
bignumber: ${random.long}
# 10以内的随机数
test1: ${random.int(l0)}
# 10-20的随机数
test2: ${random.int[l0,20]}
【2】 application.properties文件

${random}的配置方式主要有以下几种, 读者可作为参考使用。
#随机字符串
com.didispace.blog.value=${random.value}
#随机int
com.didispace.blog.number=${random.int}
#随机long
com.didispace.blog.bignumber=${random.long}
# 10以内的随机数
com.didispace.blog.tes七 1=${random.int(l0)}
# 10-20的随机数
com.didispace.blog.test2=${random.int[l0,20]}
2.5 命令行参数

启动SpringBoot应用, 可以使用命令java -jar 来启动的方式。 当然,该命令除了启动应用之外, 还可以在命令行中指定应用的参数, 比如java -jar xxx.jar --server.port = 8080,直接以命令行的方式来设置server.port属性, 并将启动应用的端口设为8080。

在用命令行方式启 动 Spring Boot 应用时, 连续的两个减号“- -”就是对application.properties中的属性值进行赋值的标识。 所以 , java -jar xxx.jar--server.port = 8080命令, 等价于在 application.properies中添加属性server.port = 8080。

通过命令行来修改属性值是 SpringBoot非常重要的一个特性。 通过此特性, 理论上已经使得应用的属性在启动前是可变的, 所以其中的端口号也好、 数据库连接也好, 都是可以在应用启动时发生改变的, 而不同于以往的Spring应用通过Maven的Profile在编译器中进行不同环境的构建。

SpringBoot的这种方式, 可以让应用程序的打包内容贯穿开发、测试以及线上部署, 而Maven不同Profile的方案为每个环境所构建的包,其内容本质上是不同的。 但是, 如果 每个参数都需要通过命令行来指定, 这显然也不是 一个好的方案, 所以下面我们看看如何在SpringBoot中实现多环境的配置。

2.6 多环境配置

我们在开发应用的时候, 通常同一套程序会被应用和安装到几个不同的环境中, 比如开发 、 测试、 生产等。 其中 每个环境的数据库地址、 服务器端口等配置都不同, 如果在为不同环境打包时都要频繁修改配置文件的话, 那必将是个非常烦琐且容易发生错误的事。

对于多环境的配置,各种项目构建工具或是框架的基本思路是 一致的, 通过配置多份不同环境的配置文件,再通过打包命令指定需要打包的内容之后进行区分打包,SpringBoot也不例外, 或者说实现起来更加简单。

在 Spring Boot 中, 多环境配置的文件名需要满足 application-{profile}.properties的格式, 其中{profile}对应你的环境标识, 如下所示:

• application-dev.properties: 开发环境。

• application-test.properties: 测试环境。

• application-prod.properties: 生产环境。

至于具体哪个配置文件会被加载, 需要在 application.properties 文件中通过spring.profiles.active 属性来设置, 其 值 对应配置文件中的{profile}值。 如spring.profiles.active= test就会加载 application-test.properties配置文件内容。

下面, 以不同环境配置不同的服务端口为例, 进行样例实验。

• 针对各环 境新建不同的配置文件 application-dev.properties 、application-test.properties、 application-prod.properties。

• 在这三个文件中均设置不同的 server.port属性, 例如, dev环境设置为1111,test环境设置为2222, prod环境设置为3333。

• application.properties中设置 spring.profiles.active= dev, 意为默认以dev环境设置。

• 测试不同配置的加载。

• 执行java -jar xxx.jar, 可以观察到服务端口被设置为1111 , 也就是默认的开发环境(dev)。

• 执行java -jar xxx.jar --spring.profiles.ac巨ve=test, 可以观察到服务端口被设置为2222, 也就是测试 环境的配置C test)。

• 执行java -jar xxx.jar --spring.profiles.active=prod, 可以观察到服务端口被设置为3333, 也就是生产环境的配置(prod)。按照上面的实验, 可以如下总结多环境的配置思路:

• 在application.properties中配置通用内容,并设置spring.profiles.active=dev, 以开发环境为默认配置。

• 在 application-{profile}.properties中配置各个环境不同的内容。

• 通过命令行方式去激活不同环境的配置。

2.7 加载顺序

在上面的例子中, 我们将SpringBoot应用需要的配置内容都放在了项目工程中, 已经能够通过spring.profiles.active或是通过Maven来实现多环境的支待。 但是, 当团队逐渐壮大, 分工越来越细致之后, 往往不需要让开发人员知道测试或是生产环境的细节, 而是希望由每个环境各自的负责人(QA或是运维)来集中维护这些信息。 那么如果还是以这样的方式存储配置内容, 对于不同环境配置的修改就不得不去获取工程 内容来修改这些配置内容, 当应用非常多的时候就变得非常不 方便。 同时, 配置内容对 开发人员都可见, 这本身也是一种安全隐患。 对此, 出现了很多将 配置内容外部化的框架和工具, 后续将要介绍的Spring Cloud Config 就是其中之一, 为了后续能更好地理解Spring Cloud Config的加载机制, 我们需要对SpringBoot对数据文件的加载机制有一定的了解。

为了能够更合理地重写各属性的值,SpringBoot使用了下面这种较为特别的属性加载顺序:

1. 在命令行中传入的参数。

2. SPRING APPLICATION JSON中的属性。 SPRING_APPLICATION—JSON是以JSON格式配置在系统环境变量中的内容。

3. java:comp/env中的JNDI 属性。

4. Java的系统属性, 可以通过System.getProperties()获得的内容。

5. 操作系统的环境变量 。

6 . 通过random.*配置的随机属性。

7. 位于当前应用 jar 包之外,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件。

8. 位于当前应用 jar 包之内 ,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件。

9. 位于当前应用jar包之外的application.properties和YAML配置内容。

10. 位于当前应用jar包之内的application.properties和YAML配置内容。

11. 在@Configuration注解修改的类中,通过@PropertySource注解定义的属性。

12. 应用默认属性,使用SpringApplication.setDefaultProperties 定义的内容。

优先级按上面的顺序由高到低,数字越小优先级越高。

可以看到,其中第7项和第9项都是从应用jar包之外读取配置文件,所以,实现外部化配置的原理就是从此切入,为其指定外部配置文件的加载位置来取代jar包之内的配置内容。 通过这样的实现,我们的工程在配置中就变得非常干净,只需在本地放置开发需要的配置即可,而不用关心其他环境的配置,由其对应环境的负责人去维护即可。
————————————————
http://www.lukou.com/user/1455521?ref=thegreat
原文链接:https://blog.csdn.net/qq_27706119/article/details/105823628

http://www.lukou.com/user/1419386?ref=thegreat

http://www.lukou.com/user/1572449?ref=thegreat

猜你喜欢

转载自www.cnblogs.com/dasdfdfecvcx/p/12891922.html