Spring Boot配置動態(tài)更新問題
SpringBoot配置動態(tài)更新
解釋
配置動態(tài)更新在本文中指當(dāng)更改應(yīng)用的配置項(xiàng)后,無需要重啟應(yīng)用新配置即可生效。
概述
配置動態(tài)更新是應(yīng)用的一種通用性需求,很實(shí)現(xiàn) 的方式有很多種,如監(jiān)聽配置文件內(nèi)容變化、使用配置中心等等。
Spring Boot在配置動態(tài)更新上本身提供了支持,我們在未使用配置中心的情況也可以簡單地實(shí)現(xiàn)配置動態(tài)更新。
實(shí)現(xiàn)方式
- 添加依賴包:spring-boot-starter-actuator、spring-cloud-starter-config,其中spring-boot-starter-actuator為Spring Boot提供的應(yīng)用監(jiān)控與管理模塊,spring-cloud-starter-config提供了refresh端點(diǎn)(endpoint)
- 使用@Value注解引用配置文件(如application.xml)中配置項(xiàng)
- 在類或者方法上添加@RefreshScope注解
- 啟動應(yīng)用
- 在配置文件中添加management.security.enabled=false配置項(xiàng),用于關(guān)閉管理模塊安全認(rèn)證,否則需要用戶登錄與相關(guān)權(quán)限
- 更改配置文件(如application.xml)中配置項(xiàng)
- 向refresh端點(diǎn)(endpoint)發(fā)送post請求,即通過post訪問http://host:port/refresh
- 訪問refresh端點(diǎn)后,Spring Boot會判斷哪些配置項(xiàng)發(fā)生了更改,添加了·@RefreshScope注解的bean如果引用了被更改配置項(xiàng)則會重新創(chuàng)建bean實(shí)例。
創(chuàng)建新的bean實(shí)例后再獲取相應(yīng)bean時,bean中的配置值已動態(tài)更新完成。
SpringBoot設(shè)置動態(tài)定時任務(wù)
在不借助Nacos、Apollo等配置中心情況下,實(shí)現(xiàn)動態(tài)修改定時任務(wù)執(zhí)行時間
實(shí)現(xiàn)
1、配置文件
#每5秒鐘執(zhí)行一次任務(wù) print.time.cron=0/5 * * * * ?
2、配置類
package com.schedule.demo.config; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; /** ?* @author zhangy ?* @date 2022/10/12 21:05 ?*/ @Data @Configuration public class ScheduleCronProperties { ? ? @Value("${print.time.cron}") ? ? private String cron; }
3、定時任務(wù)配置類
package com.schedule.demo.task; import com.schedule.demo.config.ScheduleCronProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; import java.time.LocalDateTime; /** ?* 動態(tài)定時任務(wù),可即時修改執(zhí)行時間 ?* ?* @author zhangy ?* @date 2022/10/12 21:04 ?*/ @Component public class DynamicScheduleTask implements SchedulingConfigurer { ? ? private static final Logger LOGGER = LoggerFactory.getLogger(DynamicScheduleTask.class); ? ? @Autowired ? ? private ScheduleCronProperties cronProperties; ? ? @Override ? ? public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { ? ? ? ? // 動態(tài)使用cron表達(dá)式設(shè)置循環(huán)間隔 ? ? ? ? taskRegistrar.addTriggerTask( ? ? ? ? ? ? ? ? // 需要執(zhí)行的任務(wù) ? ? ? ? ? ? ? ? () -> LOGGER.info("Now time:{}", LocalDateTime.now()), ? ? ? ? ? ? ? ? // 傳入定時任務(wù)觸發(fā)器的上下文,構(gòu)建一個新的cron觸發(fā)器對象,并獲取下次執(zhí)行的時間 ? ? ? ? ? ? ? ? triggerContext -> { ? ? ? ? ? ? ? ? ? ? // 使用CronTrigger觸發(fā)器,可動態(tài)修改cron表達(dá)式來操作循環(huán)規(guī)則 ? ? ? ? ? ? ? ? ? ? CronTrigger cronTrigger = new CronTrigger(cronProperties.getCron()); ? ? ? ? ? ? ? ? ? ? // 計(jì)算出下次執(zhí)行時間 ? ? ? ? ? ? ? ? ? ? return cronTrigger.nextExecutionTime(triggerContext); ? ? ? ? ? ? ? ? }); ? ? ? ? LOGGER.info("init success!"); ? ? } }
非lambda表達(dá)式形式
? ? @Override ? ? public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { ? ? ? ? // 需要執(zhí)行的任務(wù) ? ? ? ? Runnable runnable = new Runnable() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? LOGGER.info("Now time:{}", LocalDateTime.now()); ? ? ? ? ? ? } ? ? ? ? }; ? ? ? ? // 構(gòu)建一個新的cron觸發(fā)器對象,并獲取下次執(zhí)行的時間 ? ? ? ? Trigger trigger = new Trigger() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public Date nextExecutionTime(TriggerContext triggerContext) { ? ? ? ? ? ? ? ? // 使用CronTrigger觸發(fā)器,可動態(tài)修改cron表達(dá)式來操作循環(huán)規(guī)則 ? ? ? ? ? ? ? ? CronTrigger cronTrigger = new CronTrigger(cronProperties.getCron()); ? ? ? ? ? ? ? ? // 計(jì)算出下次執(zhí)行時間 ? ? ? ? ? ? ? ? return cronTrigger.nextExecutionTime(triggerContext); ? ? ? ? ? ? } ? ? ? ? }; ? ? ? ? taskRegistrar.addTriggerTask(runnable, trigger); ? ? ? ? LOGGER.info("init success!"); ? ? }
4、修改cron表達(dá)式的接口
該接口可以的http的也可以是其他形式的,核心邏輯就是修改ScheduleCronProperties 對象的cron屬性
package com.schedule.demo.controller; import com.alibaba.fastjson.JSONObject; import com.schedule.demo.config.ScheduleCronProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * cron表達(dá)式修改 * * @author zhangY * @date 2021-07-15 20:24:19 */ @RestController @RequestMapping("/cron") public class CronController { ? ?private static final Logger LOGGER = LoggerFactory.getLogger(CronController.class); ? ?@Autowired ? ?private ScheduleCronProperties scheduleCronProperties; ? ?@GetMapping("/get") ? ?public String get() { ? ? ? ?return JSONObject.toJSONString(scheduleCronProperties); ? ?} ? ?@GetMapping("/update") ? ?public String update(String newCron) { ? ? ? ?String oldCron = scheduleCronProperties.getCron(); ? ? ? ?LOGGER.info("update cron, old:[{}] new:[{}]", oldCron, newCron); ? ? ? ?scheduleCronProperties.setCron(newCron); ? ? ? ?//TODO 這里可以回寫配置文件或者數(shù)據(jù)庫 ? ? ? ?return JSONObject.toJSONString(scheduleCronProperties); ? ?} }
測試
項(xiàng)目啟動,自動執(zhí)行初始的5秒鐘執(zhí)行一次的任務(wù),結(jié)果如下:
Now time:2022-10-12T22:11:35
Now time:2022-10-12T22:11:40
Now time:2022-10-12T22:11:45
Now time:2022-10-12T22:11:50
Now time:2022-10-12T22:11:55
調(diào)用接口修改cron表達(dá)式
http://127.0.0.1:8080/cron/update?newCron=0/3 * * * * ?
修改后,任務(wù)執(zhí)行結(jié)果如下:
Now time:2022-10-12T22:13:25
Now time:2022-10-12T22:13:27
Now time:2022-10-12T22:13:30
Now time:2022-10-12T22:13:33
Now time:2022-10-12T22:13:36
Now time:2022-10-12T22:13:39
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java并發(fā)編程之阻塞隊(duì)列(BlockingQueue)詳解
這篇文章主要介紹了詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理,阻塞隊(duì)列是Java util.concurrent包下重要的數(shù)據(jù)結(jié)構(gòu),有興趣的可以了解一下2021-09-09詳解java數(shù)組進(jìn)行翻轉(zhuǎn)的方法有哪些
這篇文章主要介紹了詳解java數(shù)組進(jìn)行翻轉(zhuǎn)的方法有哪些,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01基于Map的computeIfAbsent的使用場景和使用方式
這篇文章主要介紹了基于Map的computeIfAbsent的使用場景和使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Elasticsearch term 查詢之精確值搜索功能實(shí)現(xiàn)
term查詢是Elasticsearch中用于精確值搜索的一種基本方式,通過了解 term 查詢的工作原理和使用方法,你可以更好地利用 Elasticsearch 進(jìn)行結(jié)構(gòu)化數(shù)據(jù)的搜索和分析,本文將詳細(xì)介紹 term 查詢的工作原理、使用場景以及如何在 Elasticsearch 中應(yīng)用它,感興趣的朋友一起看看吧2024-06-06解析WeakHashMap與HashMap的區(qū)別詳解
本篇文章是對WeakHashMap與HashMap的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05spring?security需求分析與基礎(chǔ)環(huán)境準(zhǔn)備教程
這篇文章主要為大家介紹了spring?security需求分析與基礎(chǔ)環(huán)境準(zhǔn)備教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03