一、配置文件的加载顺序
1、不同配置文件类型的加载顺序
springboot支持三种类型的配置文件
.yml
.yaml
.properties
当这三种配置文件处于同一目录下时,springboot会优先加载properties文件,如果.properties文件和.yml文件都有某一配置,而它们又处于同一目录下,那么springboot会使用.properties的配置;只有当.properties中没有某些配置时,它才会去采用.yml的这些配置。
2、项目包内-不同位置的配置文件的加载顺序(以下均以yml文件为例)
项目启动后扫描顺序:
1、先去项目根目录的config文件夹下找配置文件;
2、再去项目根目录下找配置文件;
3、再去项目resources下的config文件夹下找配置文件;
4、再去项目resources下找配置文件;
相同的配置项,springboot会以加载到的内容为准;
不同的配置项,springboot会对多个配置采取并集的操作;
上述介绍的配置文件都处于项目内部,它们在项目打包时都会被打进jar包,如果想要更改,需要重新打包。
3、项目包外-不同位置的配置文件的加载顺序
有的时候,有些配置在开发时并不知道内容为何;或者有些配置,需要在上线后的某个时刻再作修改;这时如果用上面的配置文件,那就需要重新改配置文件、打包、发版了,很麻烦。
springboot在打包时不会把项目的上级、或上级的config文件夹打入jar包(即./ 或 ./config),但是它会读取这两个地方的配置文件,而且它的读取优先级在包内配置文件之前;这个设计很巧妙,它解决了我们无法动态修改项目配置的痛点。
不同位置配置文件加载顺序总结
springboot加载配置文件的总顺序:
1、先加载包外上一级的config文件夹下的配置文件;
2、再加载包外上一级的配置文件;
3、先去项目根目录的config文件夹下找配置文件;
4、再去项目根目录下找配置文件;
5、再去项目resources下的config文件夹下找配置文件;
6、再去项目resources下找配置文件;
生产应用实例
公司有一个容器部署平台,我刚入职不久就听同事说,该平台下的configMap可以实现动态刷新配置;你给项目配置好configMap,后面有需要改的配置,只需要在configMap中修改一下配置文件、再伸缩一下容器实例,新改的配置内容就可以生效了。
过了几天,我接到开发任务,给一个项目配置configMap;
我仿照其它项目,进行了配置,主要有两个个部分:
一是,在容器平台新增一个configMap项,在里面把现在的application.yml配置上去;
二是,在项目的deploy.yaml中进行配置,这个deploy.yaml文件用于告诉容器平台,我都有哪些配置,它们的位置应该在容器的哪里。
接着进行测试,但是发现配置并未生效,比如我把项目的数据库名称故意改错,伸缩实例后项目仍可正常运行;再比如,我专门写一个测试接口,其功能就是读取某个配置项的内容,我在configmap中把这个配置项作了修改,但是调接口返回的仍然是没改之前的值;最后,我甚至清空了configMap中application.yml的内容,但是项目还是能正常运行…
我找了容器平台的同事给帮忙看看怎么回事,他们排查以后,告诉我,我的configMap配置没问题,已经生效了;它们的configMap只是保证在这里配置的内容,会在容器内、deploy.yaml指定的位置生成一个对应的文件,而且该容器内文件的内容会随着configMap对应内容的修改而修改。我的配置,现在就已经是这样了,至于接口返回值没变、数据库名改错页面也正常,这就是代码的问题了,不关他们平台的事情。
后来经过艰苦卓绝的思考,我终于想明白了;
其实之前同事说的configMap动态同步配置的功能是真的,但它不是configMap实现的、或者说不是configMap单独实现的;
它其实就是springboot加载配置文件的顺序决定的。
你只要把配置文件放在springboot会加载的地方,而且保证它比项目的application配置文件先加载,那么久可以实现动态修改配置文件;
而项目的配置文件都是放在resources下边的,我们只要把配置文件放在包外的config文件夹下不就可以了。
事实上,正是如此,我的configMap配置之所以“没生效”,就是因为configMap哪里的配置文件位置不能随意指定,它必须在包的上一级/上一级的config文件夹下,这样它才能即不用重新打包就可以让springboot读取到、又能比包内的resources文件夹下的配置文件先被读到。
而公司容器平台的configMap确实如同事所说,它只是为了你修改配置文件方便,你在configMap页面修改了,人家给你同步到容器指定的位置的文件中,至于项目读不读就不算configMap管的了。
4、通过启动命令,指定配置文件的位置
如果外部的配置文件不想放在默认的位置,可以在启动命令中,用–spring.config.location指定配置文件的位置
# 正常的启动命令
java -jar xx-1.0.0.jar --server.port=8082# 指定配置文件位置的启动命令
java -jar xx-1.0.0.jar --server.port=8082 --spring.config.location=./test/application.yml
二、springboot常用功能
1、定时任务
1)按一定频率循环触发的定时任务
对于该类型的定时任务,springboot的实现方式非常简单,只需要两步:
第一步,在启动类添加@EnableScheduling注解,使定时任务可用;
第二步,在需要定时执行的方法上加@Scheduled注解,开启定时任务,例如:
@Component
public class GlobalTokenManager {@Scheduled(fixedRate = 82800000) // 每23小时刷新一次tokenpublic void scheduledRefreshToken() throws BusinessException {refreshToken();}
}
2)需要特定行为触发的定时任务
有时候,我们需要的不是按固定时间间隔执行某任务,而是在A事件发生后,开启定时,定时结束执行B事件,结束。
这种情况可以用ScheduledExecutorService 来实现,在需要开启定时的地方新建一个ScheduledExecutorService ,其具体使用方式参考如下实例
// 开启定时任务,让车辆等待5分钟ScheduledExecutorService executor = executorConfig.initScheduledExecutor();Runnable task = new Runnable() {@Overridepublic void run() {// 5分钟结束,执行场景三的逻辑notificationParamsDto.setOrderId(order.getOrderId());notificationParamsDto.setTaskId(mqttMessageBodyVO.getTaskId());notificationService.senderDidNotArriveNotification(notificationParamsDto);}};executor.schedule(task, 5*60, TimeUnit.SECONDS);