springboot 配合Apollo实现动态定时任务配置

在使用springboot的时候,定时任务是大多系统都会实现的一个逻辑,在系统中引入了Apollo的统一配置后,我们可以通过修改定时任务执行的时间来动态更新springboot项目中定时任务的执行,Apollo配置如下:

app:
  id: smoke_detector

apollo:
  meta: http://172.12.31.217:8080
  bootstrap:
    enabled: true
    namespaces: application
    eagerLoad:
        enabled: true

在启动springboot的类上面我们一般可以加上@EnableApolloConfig()注解来启用Apollo,当然也可在其他可以初始化的地方引入,maven的Apollo引入如下:

<dependency>
   <groupId>com.ctrip.framework.apollo</groupId>
   <artifactId>apollo-client</artifactId>
   <version>1.7.0</version>
</dependency>

定时任务的类如下:

@Component
public class LoginRedisSchedule implements SchedulingConfigurer {

    @Resource
    private ScheduleSetting scheduleSetting;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(()->{
            System.out.println("zzzzzz");
        },triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(scheduleSetting.getLoginRedis());
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }

这个地方需要注意了,千万不要在类上面加注解@RefreshScope ,不要把动态配置的参数放到这里来写,不然会再次重复运行定时任务,造成错误,就像上面的我们可以定义一个setting类来单独写,如下:

@Data
@ConfigurationProperties(prefix = "schedule")
@Configuration
@RefreshScope
public class ScheduleSetting {

    @Value("${schedule.login.redis.enable}")
    private String loginRedis;

    private String follow;
}

记得这个地方一定要加上@RefreshScope注解,通过listener更新的时候才能刷新缓存,在网上其他地方参考的时候形如

@Value("${schedule.login.redis.enable}")

说会自动刷新缓存,我反正是没有刷新过,当然对于

 private String follow;

这个是必须使用@RefreshScope注解才能刷新。Apollo更新的监听代码如下:

import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import org.springframework.beans.BeansException;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * @author liaoyubo
 * @version 1.0
 * @date 2021/1/20
 * @description apollo配置修改监听
 */
@Configuration
public class ApolloConfigChangeListener implements ApplicationContextAware {

    @Resource
    private LoggingSystem loggingSystem;

    @Resource
    private RefreshScope refreshScope;


    private ApplicationContext applicationContext;

    /**
     * 日志配置常量
     */
    private static final String LOGGER_TAG = "logging.level.";

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
    public void onConfigChangeListener(ConfigChangeEvent configChangeEvent) {
        /*configChangeEvent.changedKeys()
                .stream()
                .forEach(key->{
                    ConfigChange configChange = configChangeEvent.getChange(key);
                    // 是否为日志配置
                    if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
                        // 日志配置刷新
                        changeLoggingLevel(key, configChange);
                    }else {
                        // 更新相应的bean的属性值,主要是存在@ConfigurationProperties注解的bean
                        applicationContext.publishEvent(new EnvironmentChangeEvent(configChangeEvent.changedKeys()));
                        refreshScope.refreshAll();
                    }
                });*/
        // 更新相应的bean的属性值,主要是存在@ConfigurationProperties注解的bean
        applicationContext.publishEvent(new EnvironmentChangeEvent(configChangeEvent.changedKeys()));
        refreshScope.refreshAll();
    }

    /**
     * 刷新日志级别
     */
    private void changeLoggingLevel(String key, ConfigChange change) {
        if (null == loggingSystem) {
            return;
        }
        String newLevel = change.getNewValue();
        LogLevel level = LogLevel.valueOf(newLevel.toUpperCase());
        loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
    }
}

就这样,完美了。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值