前言
Spring Boot针对常用的开发场景提供了一系列自动化配置来减少原本复杂而又几乎很少改动的模板化配置内容。
一、配置文件
Spring Boot的默认配置文件位置为src/main.resources/application.properties。关于Spring Boot应用的配置内容都可以集中在该文件中,根据我们引入的不太Starter模块,我们解压在这里定义容器端口号、数据库连接信息、日志级别等各种配置信息。eg:我们需要自定义Web模块的服务端口号可以在application.properties中添加server.port=8888来指定服务端口为8888,也可以通过spring.application.name=hello来指定应用名(该名字在后续Spring Cloud中会被注册为服务名)
Spring Boot的配置文件除了可以使用传统的properties文件之外,还支持现在被广泛推荐使用的YAML文件。
YAML是一个可读性高,用来表达资料序列的格式。YAML参考了其他多种语言,包括C语言、Python、Perl、并从XML电子邮件的数据格式中获得两个它使用空白符号缩排和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种设定文档、文件大纲。
YAML采用的配置格式不像properties的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示:
1 environments: 2 dev: 3 url:http://dev.bar.com 4 name=Developer Setup 5 prod: 6 url:http://foo.bar.com 7 name:My Cool App
等价于
1 environments.dev.url=http://dev.bar.com 2 environments.dev.name=Developer Setup 3 environments.prod.url=http://foo.bar.com 4 environments.prod.name=My Cool App
可以看到YAML的配置方式结构清晰易读,同时配置内容字符量减少。除此之外,YAML还可以在一个单独文件中通过使用spring.profiles属性来定义多个不同的环境配置。例如下面表示在指定为test环境时,server.port将使用8882端口;在prod环境中,server.port将使用8883端口;如果没有指定环境,server.port将使用8881端口。
1 server: 2 port:8881 3 --- 4 spring: 5 profiles:test 6 server: 7 port:8882 8 --- 9 spring: 10 profiles:prod 11 server: 12 port:8883 13
注:YAML无法通过@PropertySource注解来加载配置,但是YAML将属性加载到内存中保存的时候是有序的,所以当配置文件中的信息需要具备顺序含义时,YAML的配置方式比起properties配置文件更有优势。
二、自定义参数
除了可以在Spring Boot的配置文件中设置各个Starter模块中预定义的配置属性,也可以在配置文件中定义一些我们需要的自定义属性。比如在application.properties中添加
1 book.name=SpringCloudInAction 2 book.author=Slp
然后在应用中可以通过@Value注解来加载这些自定义参数,比如
1 @Component 2 public class Book{ 3 @Value("${book.name}") 4 private String name; 5 @Value("${book.author}") 6 private String author; 7 //省略getter和setter 8 }
@Value注解加载属性值的时候可以支持两种表达式来进行配置
1、PlaceHolder方式,格式为${...},{}内未PlaceHolder
2、使用SpEL表达式,格式为#{...},{}内为SpEL表达式
三、参数引用
在application.properties中的各个参数之间可以直接使用PlaceHolder的方式来应用,如:
1 book.name=SpringCloud 2 book.author=Slp 3 book.desc=${book.author} is read <${book.name}>
四、使用随机数
在一些特殊情况下,我们希望有些参数每次被加载的时候不是一个固定的值,比如秘钥、服务端口等。在Spring Boot的配置文件中,可用通过用${random}配置来生成随机的int值,long值,或者String字符串。这样就不用通过编码来实现这些逻辑。
1 #随机字符串 2 com.slp.blog.value=${random.value} 3 #随机int 4 com.slp.blog.number=${random.int} 5 #随机long 6 com.slp.blog.bignumber=${random.long} 7 #10以内的随机数 8 com.slp.blog.test1=${random.int(10)} 9 #10-20的随机数 10 com.slp.blog.test2=${random.int[10,20]}
五、命令行参数
用命令行凡是启动Spring Boot应用时,连续的2个--就是对application.properties中的属性值进行赋值的标识。所以java -jar xxx.jar --server.port=8888,等价于在application.propertirs中添加属性server.port=8888
六、多环境配置
在Spring Boot中多环节配置的文件名需要满足application-[profile].properties的格式,其中{profile}对应你的环境标识,如下所示
- application-dev.properties:开发环境
- application-test.properties:测试环境
- application-prod.properties:生产环境
至于哪个配置文件会被加载,需要在application.properties文件中通过spring.profiles.active属性来设置,其值对应配置文件中的{profile}值,如spring.profiles.active=tst就会加载application-test.properties配置文件内容、
以不同环境配置不同的服务端口为例,进行样例实验:
- 针对各环境新建不同的配置文件application-dev.properties、application-test.properties、applicatiom-prod.properties
- 针对三个文件中均设置不同的server.port属性,例如dev设置1111.test设置2222、prod设置3333
- application.properties中设置spring.profiles.active=dev,意为默认以dev环境设置
- 测试不同配置的加载
- 执行java -jar xxx.jar 可以观察到服务端口被设置为1111,也就是默认的开发环境。
- 执行java -jar xxx.jar --spring-profiles-active=test可以观察到服务端口被设置为2222,也就是测试换季的配置(test)
- 执行java -jar xxx.jar --spring-profiles.activr=prod ,可以观察到服务端口被设置为3333,也就是生产的配置
总结:
- 在application.properties中配置通用内容,并设置spring.profiles.active=dev,以开发环境为默认配置
- 在application-{profile}.properties中配置各个环境不同的内容
- 通过命令行方式去激活不同环境的配置。
七、加载顺序
为了让QA或者运维来统一维护配置信息,而 不是开发人员来自己维护,因为这本身也是一种安全隐患,对此,出现了很多配置内容外部化的框架的工具,后续将要介绍的Spring Cloud Config就是其中之一,为了更好的掌握Spring Cloud Config的加载机制,我们需要对Spring Boot对数据文件的加载机制有一定的了解。
Spring Boot使用了下面这种较为特别的属性加载顺序:
- 在命令行中传入的参数
- SPRING_APPLICATION_JAON中的属性、SPRING_APPLICATION_JAON是以JSON格式配置在系统环境变量中的内容
- java:comp/env中的JNDI属性
- Java的系统属性,可以通过System.getProperties()获得的内容
- 操作系统的环境变量
- 通过random.*配置的随机属性
- 位于当前应用jar包之外,针对不同{profile}环境的配置文件被人,例如application-{profile}.properties或是YAML定义的配置文件
- 位于当前应用jar包之内,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件
- 位于当前应用jar包之外的application.properties和YAML配置内容
- 位于当前应用jar包之内的application.properties和YAML配置内容
- 在@Configuration注解修改的类中,通过@ProeprtySource注解定义的属性
- 应用默认属性。使用SpringApplication.setDefaultProperties定义的内容
越往前优先级越高。
第7和第9都是从应用jar包之外读取配置文件,可以,实现外部化配置的原理由此切入,为其指定外部配置文件的加载位置来取代jar包纸杯的配置内容。
八、监控与管理
Spring Boot为此提供了一个Starter POMs依赖:spring-boot-starter-actuator。引入该模块能够自动为Spring Boot构建的应用提供一系列用于监控的端点,同时Spring Cloud在实现各个微服务组件的时候,进一步为该模块做了不少扩展,比如,为原生端点增加了更多的指标和度量信息(比如在整合Eureka的时候会为/health端点增加相关的信息),并且根据不同的组件还提供了更多的有空的端点(比如,为API网关组件Zuul提供了/routes端点来返回路由信息)。
1、初识actuator
在Spring Boot应用中引入该模块,在pom.xml的dependency节点中增加spring-boot-starter-actuator的依赖
1 <dependency> 2 <!--监控模块--> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-actuator</artifactId> 5 </dependency>
2、原生端点
通过使用spring-boot-starter-actuator模块,我们已经对其有了一个初步的认识,接下来我们了解一下原生端点,根据端点的作用,可以将原生端点分为以下3大类
- 应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与SpringBoot应用模切相关的配置类信息。
- 度量指标类:获取应用程序运行过程中用于监控的度量指标,比如内存信息、线程池信息,HTTP请求统计
- 操作控制类:提供了对应用的关闭等操作类功能
应用配置类
由于Spring Boot为了改善传统Spring应用繁杂的配置内容,采用了包扫描和自动化配置的机制来加载原本集中于XML文件中的各项内容,虽然这样的想法让我们的代码变得简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使我们分析整个应用中资源和实例的各种关系变得非常困难,而这类端点可以帮助我们轻松获取一系列关于Spring应用配置内容的详细报告,比如自动化配置的报告、bean创建的报告、环境属性的报告等。
/auticonfig:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项是否满足自动化配置的各个先决条件。所以,改该短信可以帮助我们方便地找到一些自动化配置为什么没有生效的具体原因,
positiveMatches中返回的是条件匹配成功的自动化配置
negativeMatches/中返回的是条件不匹配的自动化配置
/beans:该端点用来获取应用上下文中创建的所有Bean
每个Bean都包含了:
bean:bean的名称
scope:bean的作用域
type:bean的java类型
resource:class文件的具体路径
dependencies:依赖的bean名称
/configprops:该端点用来获取应用中配置的属性信息报告,从下面端点返回示例的片段中,我, 看到返回了关于该短信的配置信息,prefix属性代表了属性的配置前缀,properties代表了各个属性的名称和值,所以我们可以通过该报告来看到各个属性的配置路径,比如我们需要关闭该端点,就可以通过使用endpoints.configprops.enabled=false来完成设置。
/env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告。包括环境变量、JVM属性,应用的配置属性、命令行的参数。
/mappings:该端点用来返回所有Spring MVCde 控制器映射关系报告。
/info:该端点用来返回一些应用自定义的信息,默认情况下,该端点只会返回一个空的JSON内容,可以在application.properties配置文件中通过info前缀来设置一些属性。eg:info.app.name=spring-boot-hello info.app.version=v1.0.0
度量指标类
应用配置类端点提供的是静态报告,而度量指标类提供的报告内容则是动态变化的,这些端点提供了应用程序在运行中的一些快照信息,比如内存使用情况、HTTP请求统计、外部资源指标等。
/metrics:该端点用来返回当前应用的各类重要度量指标,比如内存信息、线程信息、垃圾回收信息等。
/health:它用来获取应用的各类健康指标信息。在spring-boot-starter-actuator模块中自带实现了一些常用西苑的健康指标检测器。这些检测器都通过HealthIndicator接口实现,并且会根据依赖关系的引入实现自动化装配。
检测器 | 功能 |
DiskSpaceHealthIndicator | 低磁盘空间检测 |
DataSourceHealthIndicator | 检测DataSource的连接是否可用 |
MongoHealthIndicator | 检测Mongo数据库是否可用 |
RabbitHealthIndicator | 检测Rabbit服务器是否可用 |
RedisHealthIndicator | 检测Reis服务器是否可用 |
SolrHealthIndicator | 检测Solr服务器是否可用 |
有时候,我们可能会用到一些Spring Boot的Starter POMS中还没有封装的产品来进行开发,比如,当使用RocketMQ作为消息代理时,由于没有自动化配置的检测器,所以我们需要自己来实现一个用来采集健康信息的检测器。我们可以在Spring Boot的应用中为org.springframework.boot.actuator.health.HealthIndicator接口实现一个对RocketMQ的检测类: