热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

springboot动态定时任务的实现方法示例

这篇文章主要给大家介绍了关于springboot动态定时任务的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、maven引入quartz包



 org.quartz-scheduler
 quartz
 2.3.2

2、创建定时任务工厂类

/**
 * 定时任务工厂类
 */
@Component
public class JobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

 private transient AutowireCapableBeanFactory beanFactory;

 @Override
 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
 final Object jobInstance = super.createJobInstance(bundle);
 beanFactory.autowireBean(jobInstance);
 return jobInstance;
 }

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

}

3、创建定时任务抽象类

public abstract class AbstractTask implements Job {

 private Logger logger = LoggerFactory.getLogger(AbstractTask.class);

 protected abstract void executeInternal(JobExecutionContext context) throws Exception;

 /**
 * 定时任务标识
 */
 private String key;

 /**
 * 数据库里配置的主键id
 */
 private Long dataBaseId;

 @Override
 public void execute(JobExecutionContext context) {
 try {
  executeInternal(context);
 } catch (Exception e) {
  logger.error(e.getMessage(), e);
  logger.error("job execute failed!");
 }
 }

 public String getKey() {
 return key;
 }

 public void setKey(String key) {
 this.key = key;
 }

 public Long getDataBaseId() {
 return dataBaseId;
 }

 public void setDataBaseId(Long dataBaseId) {
 this.dataBaseId = dataBaseId;
 }
}

4、创建定时任务业务实现类

这里可以写你的业务代码,实现具体的业务逻辑。

@Component("JobTask")
public class JobTask extends AbstractTask {

 @Override
 protected void executeInternal(JobExecutionContext context) {
 System.out.println("key = " + this.getKey());
 System.out.println("dataBaseId = " + this.getDataBaseId());
 }

}

5、创建定时任务管理器

包括项目启动时添加定时任务,手动添加定时任务,更新定时任务,删除定时任务方法。

/**
 * 定时任务管理容器 component (单例模式)
 */
@Component
@Scope("singleton")
public class JobQuartzManager implements ApplicationContextAware {

 /**
 * 创建新的scheduler
 */
 private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

 private Scheduler scheduler;

 /**
 * 定义组名称,不同的组用于区分任务
 */
 private static final String JOB_GROUP_NAME = "JOB_GROUP_NAME";

 private static final String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_NAME";

 /**
 * 日志
 */
 private Logger logger = LoggerFactory.getLogger(JobQuartzManager.class);

 private ApplicationContext applicationContext;

 @Autowired
 private JobFactory jobFactory;

 public void start() {
 //启动定时任务(初始化)
 try {
  this.scheduler = schedulerFactory.getScheduler();
  scheduler.setJobFactory(jobFactory); //设置定时任务工厂模式
  //项目启动时默认给spring容器添加动态的定时任务
  this.addJob("job" + 100L, 100L, JobTask.class, "0/2 * * * * ?");
 } catch (SchedulerException e) {
  logger.error(e.getMessage(), e);
  throw new RuntimeException("init Scheduler failed");
 }
 }

 public boolean addJob(String jobName, Long dataBaseId, Class jobClass, String cronExp) {
 boolean result = false;
 if (!CronExpression.isValidExpression(cronExp)) {
  logger.error("Illegal cron expression format({})", cronExp);
  return result;
 }
 try {
  JobDetail jobDetail = JobBuilder.newJob().withIdentity(new JobKey(jobName, JOB_GROUP_NAME))
   .ofType((Class) Class.forName(jobClass.getName()))
   .build();
  //创建完jobDetail之后,使用语句传参数值,方便定时任务内部识别它是什么标识
  JobDataMap jobDataMap = jobDetail.getJobDataMap();
  jobDataMap.put("key", jobName);
  jobDataMap.put("dataBaseId", dataBaseId);
  Trigger trigger = TriggerBuilder.newTrigger()
   .forJob(jobDetail)
   .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
   .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME))
   .build();
  scheduler.scheduleJob(jobDetail, trigger);
  scheduler.start();
  result = true;
 } catch (Exception e) {
  logger.error(e.getMessage(), e);
  logger.error("QuartzManager add job failed");
 }
 return result;
 }

 public boolean updateJob(String jobName, String cronExp) {
 boolean result = false;
 if (!CronExpression.isValidExpression(cronExp)) {
  logger.error("Illegal cron expression format({})", cronExp);
  return result;
 }
 JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
 TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);
 try {
  if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
  JobDetail jobDetail = scheduler.getJobDetail(jobKey);
  Trigger newTrigger = TriggerBuilder.newTrigger()
   .forJob(jobDetail)
   .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
   .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME))
   .build();
  scheduler.rescheduleJob(triggerKey, newTrigger);
  result = true;
  } else {
  logger.error("update job name:{},group name:{} or trigger name:{},group name:{} not exists..",
   jobKey.getName(), jobKey.getGroup(), triggerKey.getName(), triggerKey.getGroup());
  }
 } catch (SchedulerException e) {
  logger.error(e.getMessage(), e);
  logger.error("update job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
 }
 return result;
 }

 public boolean deleteJob(String jobName) {
 boolean result = false;
 JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
 try {
  if (scheduler.checkExists(jobKey)) {
  result = scheduler.deleteJob(jobKey);
  } else {
  logger.error("delete job name:{},group name:{} not exists.", jobKey.getName(), jobKey.getGroup());
  }
 } catch (SchedulerException e) {
  logger.error(e.getMessage(), e);
  logger.error("delete job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
 }
 return result;
 }

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

}

6、创建定时任务启动类

项目运行时给spring注入定时任务

/**
 * 定时任务启动类
 */
@Component
public class JobRunner implements ApplicationRunner {

 //注入定时任务管理器
 @Autowired
 private JobQuartzManager quartzManager;

 /**
 * 项目启动时激活定时任务
 */
 @Override
 public void run(ApplicationArguments applicationArguments) {
 System.out.println("--------------------注入定时任务---------------------");
 quartzManager.start();
 System.out.println("--------------------定时任务注入完成---------------------");
 }

}

7、测试案例

@RestController
@RequestMapping("/job")
public class JobController {

 @Autowired
 JobQuartzManager quartzManager;

 @PostMapping("addJob")
 @ResponseBody
 public String addJob(@RequestParam("dataBaseId") Long dataBaseId, @RequestParam("cronExp") String cronExp){
 boolean success = quartzManager.addJob("job" + dataBaseId, dataBaseId, JobTask.class, cronExp);
 if(success){
  return "添加成功";
 }else{
  return "添加失败!";
 }
 }

 @PostMapping("deleteJob")
 @ResponseBody
 public String deleteJob(@RequestParam("jobName") String jobName){
 boolean success = quartzManager.deleteJob(jobName);
 if(success){
  return "删除成功";
 }else{
  return "删除失败!";
 }
 }

 @PostMapping("updateJob")
 @ResponseBody
 public String updateJob(@RequestParam("jobName") String jobName, @RequestParam("cronExp") String cronExp){
 boolean success = quartzManager.updateJob(jobName, cronExp);
 if(success){
  return "更新成功";
 }else{
  return "更新失败!";
 }
 }

}

总结

到此这篇关于springboot实现动态定时任务的文章就介绍到这了,更多相关springboot动态定时任务内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 本文将深入探讨如何在不依赖第三方库的情况下,使用 React 处理表单输入和验证。我们将介绍一种高效且灵活的方法,涵盖表单提交、输入验证及错误处理等关键功能。 ... [详细]
  • 本文详细介绍了如何在 Spring Boot 应用中通过 @PropertySource 注解读取非默认配置文件,包括配置文件的创建、映射类的设计以及确保 Spring 容器能够正确加载这些配置的方法。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 本文探讨了在Linux系统上使用Docker时,通过volume将主机上的HTML5文件挂载到容器内部指定目录时遇到的403错误,并提供了解决方案和详细的操作步骤。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文探讨了在 ASP.NET MVC 5 中实现松耦合组件的方法。通过分离关注点,应用程序的各个组件可以更加独立且易于维护和测试。文中详细介绍了依赖项注入(DI)及其在实现松耦合中的作用。 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 探索电路与系统的起源与发展
    本文回顾了电路与系统的发展历程,从电的早期发现到现代电子器件的应用。文章不仅涵盖了基础理论和关键发明,还探讨了这一学科对计算机、人工智能及物联网等领域的深远影响。 ... [详细]
  • 科研单位信息系统中的DevOps实践与优化
    本文探讨了某科研单位通过引入云原生平台实现DevOps开发和运维一体化,显著提升了项目交付效率和产品质量。详细介绍了如何在实际项目中应用DevOps理念,解决了传统开发模式下的诸多痛点。 ... [详细]
  • 本文详细介绍了 Flink 和 YARN 的交互机制。YARN 是 Hadoop 生态系统中的资源管理组件,类似于 Spark on YARN 的配置方式。我们将基于官方文档,深入探讨如何在 YARN 上部署和运行 Flink 任务。 ... [详细]
  • 自己用过的一些比较有用的css3新属性【HTML】
    web前端|html教程自己用过的一些比较用的css3新属性web前端-html教程css3刚推出不久,虽然大多数的css3属性在很多流行的浏览器中不支持,但我个人觉得还是要尽量开 ... [详细]
  • 本文探讨了如何在日常工作中通过优化效率和深入研究核心技术,将技术和知识转化为实际收益。文章结合个人经验,分享了提高工作效率、掌握高价值技能以及选择合适工作环境的方法,帮助读者更好地实现技术变现。 ... [详细]
  • 本文介绍了一种在 MySQL 客户端执行 NOW() 函数时出现时间偏差的问题,并详细描述了如何通过配置文件调整时区设置来解决该问题。演示场景中,假设当前北京时间为2023年2月17日19:31:37,而查询结果显示的时间比实际时间晚8小时。 ... [详细]
author-avatar
我就是老笨2013
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有