SpringBoot提供了灵活的配置方式,如果你发现你的项目中有个别属性需要重新配置,可以使用临时属性的方式快速修改某些配置。方法也特别简单,在启动的时候添加上对应参数就可以了。
java -jar springboot.jar --server.port=80
当属性存在多级名称时,中间使用点分隔,和properties文件中的属性格式完全相同。
如果你发现要修改的属性不止一个,可以按照上述格式继续写,属性与属性之间使用空格分隔。
java -jar springboot.jar --server.port=80 --logging.level.root=debug
现在我们的程序配置受两个地方控制了,第一配置文件,第二临时属性。并且我们发现临时属性的加载优先级要高于配置文件的。那是否还有其他的配置方式呢?其实是有的,而且还不少。
查看配置读取的优先顺序
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
有14种配置的位置,而我们现在使用的是这里面的2个。第3条Config data说的就是使用配置文件,第11条Command line arguments说的就是使用命令行临时参数。
列表上面的优先级低,下面的优先级高。
小结
- 使用jar命令启动SpringBoot工程时可以使用临时属性替换配置文件中的属性
- 临时属性添加方式:java –jar 工程名.jar –-属性名=值
- 多个临时属性之间使用空格分隔
- 临时属性必须是当前boot工程支持的属性,否则设置无效
临时属性目前是有了,但是上线的时候通过命令行输入的临时属性必须是正确的啊,那这些属性配置值我们必须在开发环境中测试好
才行。
打开SpringBoot引导类的运行界面,在里面找到配置项。其中Program arguments对应的位置就是添加临时属性的,可以加几个试试效果。
老版本直接在Program arguments后写就行
我们运行main方法的时候,如果想使用main方法的参数,也就是下面的args参数,就是在上面这个位置添加的参数。
public static void main(String[] args) {
}
通过这个args就可以获取到参数。再来看我们的引导类是如何书写的
public static void main(String[] args) {
SpringApplication.run(SSMPApplication.class,args);
}
这个args参数居然传递给了run方法,看来在Idea中配置的临时参数就是通过这个位置传递到我们的程序中的。言外之意,这里如果不用这个args是不是就断开了外部传递临时属性的入口呢?是这样的,我们可以使用下面的调用方式,这样外部临时属性就无法进入到SpringBoot程序中了。
public static void main(String[] args) {
SpringApplication.run(SSMPApplication.class);
}
或者还可以使用如下格式来玩这个操作,就是将配置不写在配置文件中,直接写成一个字符串数组,传递给程序入口。当然,这种做法并没有什么实际开发意义。
public static void main(String[] args) {
String[] arg = new String[1];
arg[0] = "--server.port=8082";
SpringApplication.run(SSMPApplication.class, arg);
}
小结
- 启动SpringBoot程序时,可以选择是否使用命令行属性为SpringBoot程序传递启动属性
- 删除引导类run方法中的args参数则代表不启用命令行传递属性
临时属性好用是好用,就是写的多了会很麻烦。比如我现在有个需求,上线的时候使用临时属性配置20个值,这下可麻烦了,能不能搞得简单点,集中管理一下呢?比如说搞个文件,加载指定文件?还真可以。怎么做呢?咱们下一节再说。
SpringBoot提供了配置文件和临时属性的方式来对程序进行配置。
配置文件我们一直在使用,只不过我们用的是SpringBoot提供的4级配置文件中的其中一个级别。4个级别分别是:
一直使用的是这个
,也就是resources目录中的application.yml文件)上述4种文件是提供给你了4种配置文件书写的位置,功能都是一样的,都是做配置的。那大家关心的就是差别了,没错,就是因为位置不同,产生了差异。
4种配置文件如果都存在的话,有一个优先级的问题,说白了就是加入4个文件我都有,里面都有一样的配置,谁生效的问题。
- file :config/application.yml 【最高】
- file :application.yml
- classpath:config/application.yml
- classpath:application.yml 【最低】
场景:
设计这么多种是为了减少配置改来改去,比如自己写代码的时候用classpath:application.yml这个配置文件,联调测试的时候需要修改配置(修改数据库配置,端口…),如果都在这个文件中修改的话,测试完之后接着写自己的代码,又要把它重新改回来。
用上面的3这个级别的配置文件就可以快速解决这个问题,再写一个配置就行了。两个配置文件共存,因为config目录中的配置加载优先级比你的高,所以配置项如果和级别4里面的内容相同就覆盖了。
总结
SpringBoot支持4级配置文件,应用于开发与线上环境进行配置的灵活设置
配置文件分为4种
- 项目类路径配置文件:服务于开发人员本机开发与测试
- 项目类路径config目录中配置文件:服务于项目经理整体调控
- 工程路径配置文件:服务于运维人员配置涉密线上环境
- 工程路径config目录中配置文件:服务于运维经理整体调控
多层级配置文件间的属性采用叠加并覆盖的形式作用于程序
之前咱们做配置使用的配置文件都是application.yml,其实这个文件也是可以改名字的,这样方便维护。比如我2020年4月1日搞活动,走了一组配置,2020年5月1日活动取消,恢复原始配置,这个时候只需要重新更换一下配置文件就可以了。但是你总不能在原始配置文件上修改吧,不然搞完活动以后,活动的配置就留不下来了,不利于维护。
注意:SpringBoot默认只识别名称为application的配置文件
自定义配置文件方式有如下两种:
方式一:使用临时属性设置配置文件名,注意仅仅是名称,不要带扩展名
不要带扩展名,它可以识别名称为ebank的配置文件,可以是properties,yml,yaml文件。
使用的属性一个是spring.config.name,另一个是spring.config.location,这个一定要区别清楚。
温馨提示
我们现在研究的都是SpringBoot单体项目,就是单服务器版本。其实企业开发现在更多的是使用基于SpringCloud技术的多服务器项目。这种配置方式和我们现在学习的完全不一样,所有的服务器将不再设置自己的配置文件,而是通过配置中心获取配置,动态加载配置信息。为什么这样做?集中管理。这里不再说这些了,后面再讲这些东西。
总结
- 配置文件可以修改名称,通过启动参数设定
- 配置文件可以修改路径,通过启动参数设定
- 微服务开发中配置文件通过配置中心进行设置
每个计算机环境不一样,这就是多环境。常见的多环境开发主要兼顾3种环境设置,开发环境——自己用的,测试环境——自己公司用的,生产环境——甲方爸爸用的。因为这是绝对不同的三台电脑,所以环境肯定有所不同,比如连接的数据库不一样,设置的访问端口不一样等等。
那什么是多环境开发?就是针对不同的环境设置不同的配置属性即可。比如你自己开发时,配置你的端口如下:
server:
port: 80
如何想设计两组环境呢?中间使用三个减号分隔开
server:
port: 80
---
server:
port: 81
如何区分两种环境呢?起名字呗
spring:
profiles: pro
server:
port: 80
---
spring:
profiles: dev
server:
port: 81
那用哪一个呢?设置默认启动哪个就可以了
spring:
profiles:
active: pro # 启动pro
---
spring:
profiles: pro
server:
port: 80
---
spring:
profiles: dev
server:
port: 81
就这么简单,再多来一组环境也OK
spring:
profiles:
active: pro # 启动pro
---
spring:
profiles: pro
server:
port: 80
---
spring:
profiles: dev
server:
port: 81
---
spring:
profiles: test
server:
port: 82
其中关于环境名称定义上述格式是过时格式,标准格式如下
spring:
config:
activate:
on-profile: pro
总结
- 多环境开发需要设置若干种常用环境,例如开发、生产、测试环境
- yaml格式中设置多环境使用—区分环境设置边界
- 每种环境的区别在于加载的配置属性不同
- 启用某种环境时需要指定启动时使用该环境
将所有的配置都放在一个配置文件中,尤其是每一个配置应用场景都不一样,这显然不合理,于是就有了将一个配置文件拆分成多个配置文件的想法。拆分后,每个配置文件中写自己的配置,主配置文件中写清楚用哪一个配置文件就好了
。
主配置文件
spring:
profiles:
active: pro # 启动pro
环境配置文件因为每一个都是配置自己的项,所以连名字都不用写里面了。那问题是如何区分这是哪一组配置呢?使用文件名区分。
application-pro.yaml
server:
port: 80
application-dev.yaml
server:
port: 81
文件的命名规则为:application-环境名.yml
。
在配置文件中,如果某些配置项所有环境都一样,可以将这些项写入到主配置中,只有哪些有区别的项才写入到环境配置文件中。
- 主配置文件中设置公共配置(全局)
- 环境分类配置文件中常用于设置冲突属性(局部)
SpringBoot最早期提供的配置文件格式是properties格式的,这种格式的多环境配置也了解一下吧。
主配置文件
spring.profiles.active=pro
环境配置文件
application-pro.properties
server.port=80
application-dev.properties
server.port=81
文件的命名规则为:application-环境名.properties
。
总结
- properties文件多环境配置仅支持多文件格式
作为程序员在搞配置的时候往往处于一种分久必合合久必分的局面。开始先写一起,后来为了方便维护就拆分。对于多环境开发也是如此,下面给大家说一下如何基于多环境开发做配置独立管理,务必掌握。
准备工作
将所有的配置根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下
使用
使用include属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔
spring:
profiles:
active: dev
include: devDB,devRedis,devMVC
比较一下,现在相当于加载dev配置时,再加载对应的3组配置,从结构上就很清晰,用了什么,对应的名称是什么
注意
当主环境dev与其他环境有相同属性时,主环境属性生效;其他环境中有相同属性时,最后加载的环境属性生效
改良
但是上面的设置也有一个问题,比如我要切换dev环境为pro时,include也要修改。因为include属性只能使用一次,这就比较麻烦了。SpringBoot从2.4版开始使用group属性替代include属性,降低了配置书写量。简单说就是我先写好,你爱用哪个用哪个。
spring:
profiles:
active: dev
group:
"dev": devDB,devRedis,devMVC
"pro": proDB,proRedis,proMVC
"test": testDB,testRedis,testMVC
现在再来看,如果切换dev到pro,只需要改一下是不是就结束了?完美!
总结
- 多环境开发使用group属性设置配置文件分组,便于线上维护管理
最后说一个冲突问题。就是maven和SpringBoot同时设置多环境的话怎么搞。
要想处理这个冲突问题,你要先理清一个关系,究竟谁在多环境开发中其主导地位。也就是说如果现在都设置了多环境,谁的应该是保留下来的,另一个应该遵从相同的设置。
maven是做什么的?项目构建管理的,最终生成代码包的,SpringBoot是干什么的?简化开发的。简化,又不是其主导作用。最终还是要靠maven来管理整个工程
,所以SpringBoot应该听maven的。整个确认后下面就好做了。大体思想如下:
maven中设置多环境(使用属性方式区分环境)
<profiles>
<profile>
<id>env_devid>
<properties>
<profile.active>devprofile.active>
properties>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
profile>
<profile>
<id>env_proid>
<properties>
<profile.active>proprofile.active>
properties>
profile>
profiles>
SpringBoot中读取maven设置值
spring:
profiles:
active: @profile.active@
上面的@属性名@就是读取maven中配置的属性值的语法格式。
总结
- 当Maven与SpringBoot同时对多环境进行控制时,以Mavn为主,SpringBoot使用@…@占位符读取Maven对应的配置属性值
- 基于SpringBoot读取Maven配置属性的前提下,如果在Idea下测试工程时pom.xml每次更新需要手动compile方可生效
日志其实就是记录程序日常运行的信息,主要作用如下:
@RestController
@RequestMapping("/book")
public class BookController {
private static final Logger log = LoggerFactory.getLogger(BookController.class);
@RequestMapping("test")
public void test(){
log.debug("debug...");
log.info("info...");
log.warn("warn...");
log.error("error...");
}
}
日志设置好以后可以根据设置选择哪些参与记录。这里是根据日志的级别来设置的。日志的级别分为6种,分别是:
一般情况下,开发时候使用DEBUG,上线后使用INFO,运维信息记录使用WARN即可。下面就设置一下日志级别:
# 开启debug模式,输出调试信息,常用于检查系统运行状况
debug: true
这么设置太简单粗暴了,日志系统通常都提供了细粒度的控制
# 设置日志级别,root表示根节点,即整体应用日志级别
logging:
level:
root: debug
还可以再设置更细粒度的控制
logging:
# 设置日志组
group:
# 自定义组名,设置当前组中所包含的包
ebank: com.itheima.controller
level:
root: warn
# 为对应组设置日志级别
ebank: debug
# 为对包设置日志级别
com.itheima.controller: debug
说白了就是总体设置一下,每个包设置一下,如果感觉设置的麻烦,就先把包分个组,对组设置,没了,就这些。
总结
- 日志用于记录开发调试与运维过程消息
- 日志的级别共6种,通常使用4种即可,分别是DEBUG,INFO,WARN,ERROR
- 可以通过日志组或代码包的形式进行日志显示级别的控制
优化日志对象创建代码
写代码的时候每个类都要写创建日志记录对象,这个可以优化一下,使用前面用过的lombok技术给我们提供的工具类即可。
导入lombok后使用注解搞定,日志对象名为log
@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
//可以省略
//private static final Logger log = LoggerFactory.getLogger(BookController.class);
@RequestMapping("test")
public void test(){
log.debug("debug...");
log.info("info...");
log.warn("warn...");
log.error("error...");
}
}
总结
- 基于lombok提供的@Slf4j注解为类快速添加日志对象
日志已经能够记录了,但是目前记录的格式是SpringBoot给我们提供的,如果想自定义控制就需要自己设置了。先分析一下当前日志的记录格式。
对于单条日志信息来说,日期,触发位置,记录信息是最核心的信息。级别用于做筛选过滤,PID与线程名用于做精准分析。了解这些信息后就可以DIY日志格式了。下面是模拟的官方日志模板的书写格式:
logging:
pattern:
console: "%d %clr(%p) --- [%16t] %clr(%-40.40c){cyan} : %m %n"
日志信息显示,记录已经控制住了,下面就要说一下日志的转存了。日志不能仅显示在控制台上,要把日志记录到文件中
,方便后期维护查阅。
对于日志文件的使用存在各种各样的策略,例如每日记录,分类记录,报警后记录等。这里主要研究日志文件如何记录。
记录日志到文件中格式非常简单,设置日志文件名即可。
logging:
file:
name: server.log
虽然使用上述格式可以将日志记录下来了,但是面对线上的复杂情况,一个文件记录肯定是不能够满足运维要求的,通常会每天记录日志文件,同时为了便于维护,还要限制每个日志文件的大小。下面给出日志文件的常用配置方式:
logging:
file:
name: server.log
logback:
rollingpolicy:
max-file-size: 3KB
file-name-pattern: server.%d{yyyy-MM-dd}.%i.log
以上格式是基于logback日志技术设置每日日志文件的设置格式,要求容量到达3KB以后就转存信息到第二个文件中。文件命名规则中的%d标识日期,%i是一个递增变量,用于区分日志文件
。
总结
- 日志记录到文件
- 日志文件格式设置