springboot动态任务统一管理(新增、修改、停止、删除)

springboot任务动态注册、修改、停止、删除和统一管理
github地址:https://github.com/softwarevax/maven/tree/main/unified-task-schedule
1、任务实体类

public class Job {

    /**
     * 任务id, 用于标识,默认使用全限定类名
     */
    private String jobId;

    /**
     * 任务名称, 默认简单类名
     */
    private String jobName;

    /**
     * cron表达式, 修改后即可生效
     */
    private String cron;

    /**
     * 任务描述
     */
    private String description;

    /**
     * 是否启用, 默认启用, 修改后即可生效
     */
    private boolean enable = true;

    /**
     * 是否处于等待执行下个任务的状态
     */
    private boolean active;
    /**
     * 任务运行类
     */
    private Class<? extends Runnable> clazz;
}

2、任务操作

public class JobHandler {

    private ScheduledTask scheduledTask;

    private TriggerTask triggerTask;

    private TriggerContext triggerContext;
}

3、spring动态注册bean,任务运行类中需要注入bean时,可直接注入

public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext CONTEXT;
    /**
     * 设置spring上下文
     * @param ctx spring上下文
     * @throws BeansException
     * */
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        CONTEXT = ctx;
    }

    /**
     * 获取容器
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return CONTEXT;
    }

    /**
     * 获取容器对象
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> type) {
        return CONTEXT.getBean(type);
    }

    public static <T> T getBean(String name,Class<T> clazz){
        return CONTEXT.getBean(name, clazz);
    }

    public static Object getBean(String name){
        return CONTEXT.getBean(name);
    }

    /**
     * springboot动态注册bean
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T register(Class<T> clazz) {
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) ApplicationContextUtils.getApplicationContext();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        if(defaultListableBeanFactory.getBeanNamesForType(clazz).length > 0) {
            return defaultListableBeanFactory.getBean(clazz);
        }
		defaultListableBeanFactory.registerBeanDefinition(clazz.getName(), beanDefinitionBuilder.getRawBeanDefinition());
		return (T) ApplicationContextUtils.getBean(clazz.getName());
    }
}

4、配置SchedulingConfigurer,实现动态任务的关键

public class JobSchedulingConfigurer implements SchedulingConfigurer {

    private ScheduledTaskRegistrar registrar;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        this.registrar = scheduledTaskRegistrar;
    }

    public ScheduledTaskRegistrar getRegistrar() {
        return registrar;
    }

    public void setRegistrar(ScheduledTaskRegistrar registrar) {
        this.registrar = registrar;
    }
}

5、任务增删改查

public class SchedulerManager {

    /**
     * 任务容器
     */
    private Map<Job, JobHandler> tasks = new ConcurrentHashMap<>();

    /**
     * 任务注册
     */
    @Autowired
    private JobSchedulingConfigurer register;

    /**
     * 新增任务, 自生效
     * @param job 任务实体
     * @return 返回新增的任务
     */
    public Job addJob(Job job) {
        Assert.notNull(job, "job can't be null");
        ScheduledTaskRegistrar registrar = register.getRegistrar();
        Runnable runnable = ApplicationContextUtils.register(job.getClazz());
        if(job.getJobId() == null || "".equals(job.getJobId())) {
            job.setJobId(job.getClazz().getName());
        }
        Assert.isNull(this.getJob(job.getJobId()), "任务[" + job.getJobId() + "]已存在");
        if(job.getJobName() == null || "".equals(job.getJobName())) {
            job.setJobName(ClassUtils.getShortName(job.getClazz()));
        }
        CronExpress cron = AnnotationUtils.findAnnotation(job.getClazz(), CronExpress.class);
        if(cron != null && !"".equals(cron.value())) {
            // 注解的属性,大于配置的属性,方便调试
            job.setCron(cron.value());
        }
        job.setEnable(true);
        job.setActive(true);
        JobHandler entity = new JobHandler();
        TriggerTask triggerTask = new TriggerTask(runnable, (TriggerContext triggerContext) -> {
            // 每次任务执行均会进入此方法
            CronTrigger trigger = new CronTrigger(job.getCron());
            entity.setTriggerContext(triggerContext);
            return job.isEnable() ? trigger.nextExecutionTime(triggerContext) : null;
        });
        ScheduledTask scheduledTask = registrar.scheduleTriggerTask(triggerTask);
        entity.setScheduledTask(scheduledTask);
        entity.setTriggerTask(triggerTask);
        tasks.put(job, entity);
        return job;
    }

    /**
     * 任务类(必须标注了@CronExpress注解,且实现了Runnable接口)
     * @param clazz 接口类
     * @return 任务对象
     */
    public Job addJob(Class<? extends Runnable> clazz) {
        Job job = new Job();
        job.setClazz(clazz);
        return this.addJob(job);
    }

    /**
     * 获取任务操作对象
     * @param jobId 任务id
     * @return 任务操作对象
     */
    public JobHandler getJobHandler(String jobId) {
        return tasks.get(new Job(jobId));
    }

    /**
     * 根据任务id获取任务
     * @param jobId 任务id
     * @return 任务实体
     */
    public Job getJob(String jobId) {
        Assert.hasText(jobId, "jobId can't be null");
        Set<Job> jobs = tasks.keySet();
        if(jobs.size() == 0) {
            return null;
        }
        Iterator<Job> iterator = jobs.iterator();
        while (iterator.hasNext()) {
            Job next = iterator.next();
            if(jobId.equals(next.getJobId())) {
                return next;
            }
        }
        return null;
    }

    /**
     * 关闭任务(若任务正在执行,待任务执行完)
     * @param jobId 任务id
     * @return 是否关闭成功
     */
    public boolean shutDown(String jobId) {
        try {
            JobHandler handler = this.getJobHandler(jobId);
            Assert.notNull(handler, "任务[" + jobId + "]不存在");
            handler.getScheduledTask().cancel();
            Job job = getJob(jobId);
            job.setActive(false);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 启动已经注册的任务
     * @param jobId 任务id
     * @return 是否成功启动
     */
    public boolean startUp(String jobId) {
        try {
            JobHandler handler = this.getJobHandler(jobId);
            Assert.notNull(handler, "任务[" + jobId + "]不存在");
            register.getRegistrar().scheduleTriggerTask(handler.getTriggerTask());
            Job job = getJob(jobId);
            job.setActive(true);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取所有的任务实体
     * @return
     */
    public List<Job> getJobs() {
        return new ArrayList<>(tasks.keySet());
    }

    /**
     * 删除任务,先关闭再删除
     * @param jobId
     * @return
     */
    public boolean deleteJob(String jobId) {
        try {
            Job job = this.getJob(jobId);
            Assert.notNull(job, "任务[" + jobId + "]不存在");
            shutDown(jobId);
            tasks.remove(job);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

6、任务运行类

@CronExpress("0/1 * * * * *")
public class HelloJob implements Runnable {

    @Override
    public void run() {
        System.out.println("hello msg" + Thread.currentThread().getId());
    }
}

7、测试

ConfigurableApplicationContext ctx = SpringApplication.run(UnifiedTaskScheduleStarterApplication.class, args);
SchedulerManager schedulerManager = ctx.getBean(SchedulerManager.class);
Job job = schedulerManager.addJob(com.github.softwarevax.web.HelloJob.class);
schedulerManager.shutDown(job.getJobId());

所有的任务,放在一个模块中,该模块不需要特殊依赖包,启动时,注册任务,实现统一管理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Spring Boot中,可以使用Quartz库来实现动态移除定时任务。Quartz是一个强大的调度框架,可以在后台添加、修改、移除定时任务。通过集成Quartz,可以实现在不重启应用的情况下动态移除定时任务。 可以参考中的Demo来实现动态移除定时任务的功能。在这个Demo中,后台可以添加、修改、移除定时任务,并且可以查看当前任务的状态。具体的实现可以参考Git项目地址中提供的代码。 使用Spring Boot和Quartz实现动态移除定时任务的步骤如下: 1. 首先,需要在Spring Boot项目中添加Quartz的依赖。 2. 创建一个定时任务管理类,用于管理所有的定时任务。这个类可以包含添加、修改、移除定时任务的方法。 3. 在定时任务管理类中,定义一个方法来移除定时任务。这个方法可以接受一个任务的唯一标识符作为参数,然后使用Quartz提供的API来移除该任务。 4. 在需要移除定时任务的地方,调用定时任务管理类中的移除定时任务的方法,传入要移除的任务的标识符即可。 通过以上步骤,就可以实现在Spring Boot中动态移除定时任务的功能了。这样可以在不重启应用的情况下,根据需要随时移除指定的定时任务。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Springboot2-Quartz 后台可动态配置的定时任务](https://download.csdn.net/download/qq_32923745/10981179)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring Boot实现动态增加、删除修改停止定时任务](https://blog.csdn.net/qq_43813937/article/details/104183541)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [springboot不重启应用动态添加修改删除定时任务(以cron定时方式为例)](https://blog.csdn.net/qq_37549757/article/details/94393282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值