Spring Boot配置動態(tài)更新問題
SpringBoot配置動態(tài)更新
解釋
配置動態(tài)更新在本文中指當(dāng)更改應(yīng)用的配置項后,無需要重啟應(yīng)用新配置即可生效。
概述
配置動態(tài)更新是應(yīng)用的一種通用性需求,很實現(xiàn) 的方式有很多種,如監(jiān)聽配置文件內(nèi)容變化、使用配置中心等等。
Spring Boot在配置動態(tài)更新上本身提供了支持,我們在未使用配置中心的情況也可以簡單地實現(xiàn)配置動態(tài)更新。
實現(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端點(endpoint)
- 使用@Value注解引用配置文件(如application.xml)中配置項
- 在類或者方法上添加@RefreshScope注解
- 啟動應(yīng)用
- 在配置文件中添加management.security.enabled=false配置項,用于關(guān)閉管理模塊安全認(rèn)證,否則需要用戶登錄與相關(guān)權(quán)限
- 更改配置文件(如application.xml)中配置項
- 向refresh端點(endpoint)發(fā)送post請求,即通過post訪問http://host:port/refresh
- 訪問refresh端點后,Spring Boot會判斷哪些配置項發(fā)生了更改,添加了·@RefreshScope注解的bean如果引用了被更改配置項則會重新創(chuàng)建bean實例。
創(chuàng)建新的bean實例后再獲取相應(yīng)bean時,bean中的配置值已動態(tài)更新完成。
SpringBoot設(shè)置動態(tài)定時任務(wù)
在不借助Nacos、Apollo等配置中心情況下,實現(xiàn)動態(tài)修改定時任務(wù)執(zhí)行時間
實現(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表達式設(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表達式來操作循環(huán)規(guī)則
? ? ? ? ? ? ? ? ? ? CronTrigger cronTrigger = new CronTrigger(cronProperties.getCron());
? ? ? ? ? ? ? ? ? ? // 計算出下次執(zhí)行時間
? ? ? ? ? ? ? ? ? ? return cronTrigger.nextExecutionTime(triggerContext);
? ? ? ? ? ? ? ? });
? ? ? ? LOGGER.info("init success!");
? ? }
}非lambda表達式形式
? ? @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表達式來操作循環(huán)規(guī)則
? ? ? ? ? ? ? ? CronTrigger cronTrigger = new CronTrigger(cronProperties.getCron());
? ? ? ? ? ? ? ? // 計算出下次執(zhí)行時間
? ? ? ? ? ? ? ? return cronTrigger.nextExecutionTime(triggerContext);
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? taskRegistrar.addTriggerTask(runnable, trigger);
? ? ? ? LOGGER.info("init success!");
? ? }4、修改cron表達式的接口
該接口可以的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表達式修改
*
* @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);
? ?}
}測試
項目啟動,自動執(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表達式
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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java通過調(diào)用C/C++實現(xiàn)的DLL動態(tài)庫——JNI的方法
這篇文章主要介紹了Java通過調(diào)用C/C++實現(xiàn)的DLL動態(tài)庫——JNI的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-01-01
SpringBoot如何打印mybatis的執(zhí)行sql問題
這篇文章主要介紹了SpringBoot如何打印mybatis的執(zhí)行sql問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Java自動化實現(xiàn)將HTML轉(zhuǎn)換為Word
在日常的軟件開發(fā)和企業(yè)應(yīng)用中,我們經(jīng)常會遇到需要將動態(tài)生成的 HTML 內(nèi)容轉(zhuǎn)化為規(guī)范的 Word 文檔,本文將介紹如何利用 Java 輕松實現(xiàn) HTML 到 Word 的高效轉(zhuǎn)換,需要的可以了解下2025-10-10
java如何實現(xiàn)自動生成數(shù)據(jù)庫設(shè)計文檔
以前我們還需要手寫數(shù)據(jù)庫設(shè)計文檔、現(xiàn)在可以通過引入screw核心包來實現(xiàn)Java?數(shù)據(jù)庫文檔一鍵生成。本文將具體介紹一下如何通過java自動生成數(shù)據(jù)庫設(shè)計文檔,需要的朋友可以參考下2021-11-11
SpringCloud Zuul和Gateway的實例代碼(搭建方式)
本文主要介紹了SpringCloudZuul和SpringCloudGateway的簡單示例,SpringCloudGateway是推薦使用的API網(wǎng)關(guān)解決方案,基于SpringFramework5和ProjectReactor構(gòu)建,具有更高的性能和吞吐量2025-02-02
Spring?Boot配置內(nèi)容加密實現(xiàn)敏感信息保護
之前我們講過的配置相關(guān)知識都是Spring?Boot原生就提供的,而今天我們將介紹的功能并非Spring?Boot原生就支持,但卻非常有用:配置內(nèi)容的加密2021-11-11
springboot自定義redis序列化類解決increment操作失敗的問題
這篇文章主要介紹了springboot自定義redis序列化類解決increment操作失敗的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
java動態(tài)獲取實體類字段的8種方法實現(xiàn)
本文介紹了Java中動態(tài)獲取實體類字段的多種方法,包括反射API、注解處理器、字節(jié)碼操作庫、ORM框架等,具有一定的參考價值,感興趣的可以了解一下2025-07-07

