本文前置条件:Quartz 2.2.1, Spring 3.1以上版本,Quartz 2以下类似,只是具体类中对于配置动态任务写法不同。本文所说的动态是指把定时任务动态配置在数据库中。
本文只是简单的写下思路,写的不好请见谅!
主要思路如下:
1)首先配置一个定时任务的类,TaskInfo,可以如下
/** * 定时任务信息 * */ public class TaskInfo { /** 任务id */ private long jobId; /** 定时任务全路径 ,定时任务必须实现AbsTask eg com.task */ private String jobClass; /** 任务名称 */ private String jobName; /** 任务分组 */ private String jobGroup; /** 任务状态 0禁用 1启用 2删除 */ private String jobStatus; /** 任务运行时间表达式 */ private String cronExpression; /** 任务描述 */ private String desc; public long getJobId() { return jobId; } public void setJobId(long jobId) { this.jobId = jobId; } public String getJobClass() { return jobClass; } public void setJobClass(String jobClass) { this.jobClass = jobClass; } public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } public String getJobStatus() { return jobStatus; } public void setJobStatus(String jobStatus) { this.jobStatus = jobStatus; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this.cronExpression = cronExpression; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
2)要想动态配置,必须先配置一个后台定时任务在一定间隔内扫描表中的数据,且该后台定时任务不能重复配置,彻底点就是禁止改后台定时任务出现在表中
3)为和后台定时任务区分,可以定义一个抽象类,具体类必须实现该类的方法。抽象类中的方法可以类似于 execute(long taskId),这样好处是可以在数据库中配置一张定时任务运行参数表,不配置参数表也行。
4)具体功能的类实现抽象类
5)由于在类中配置定时任务时候,创建JobDetail时候具体任务类必须实现Job接口,如下所示
JobDetail jobDetail = JobBuilder.newJob(TaskRegJob.class) .withIdentity(task.getJobName(), task.getJobGroup()) .build();
所以要一个实现了Job接口的定时任务作为中介,该定时任务以配置的Cron表达式运行,在
public void execute(JobExecutionContext context) throws JobExecutionException {
方法内调用配置类的方法。
6)用于数据库中的数据在后台定时任务运行间隔内可能被删除,可以能被新增或者修改,这里只有删除特殊点,新增只是在配置个TaskRegJob而已,修改则只需要改下定时任务的Cron表达式而已,删除的定时任务可能正在运行,这时候就要想个办法处理,本人认为可以这样处理:
在TaskScanJob后台定时任务方法内先删除没有正在运行的定时任务,如何得到正在运行的定时任务可以这样做:
Scheduler scheduler = context.getScheduler(); List runningJobs = null; try { runningJobs = scheduler.getCurrentlyExecutingJobs(); } catch (SchedulerException e) { e.printStackTrace(); }
判断是否正在运行:
private static boolean isRunning(JobKey jobKey, List runningJobs) throws Exception { boolean rtn = false; for (Iterator iter = runningJobs.iterator(); iter.hasNext();) { JobExecutionContext item = (JobExecutionContext) iter.next(); if ((item.getJobDetail().getKey().equals(jobKey))) { rtn = true; break; } } return rtn; }
得到当前配置的所有定时任务:
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); try { Set<JobKey> jobKeys = scheduler.getJobKeys(matcher); for (JobKey jobKey : jobKeys) { }
删除定时任务:
boolean rtn = scheduler.deleteJob(jobKey);
删除的定时任务在下次启动时生效
在TaskRegJob定时任务中,使用taskId去数据库取定时任务信息,如果取不到说明该定时任务已经被删除,只是用于正在运行所以不满足运行完成条件没有被删除,这时候可以这样做:
try { taskId = data.getLong("TASK_ID"); task = DB.getTaskById(taskId); } catch (Throwable ex) { log.error("任务执行异常,任务ID:" + taskId + ",有可能的原因是,此任务已经加入调度,执行时此任务已经被删除", ex); try { log.info("准备删除当前任务:" + context.getJobDetail().getKey()); context.getScheduler().deleteJob( context.getJobDetail().getKey()); } catch (SchedulerException e) { throw new JobExecutionException("任务删除异常,任务ID:" + taskId + ",有可能的原因是:", ex); } throw new JobExecutionException("任务执行异常,任务ID:" + taskId + ",有可能的原因是,此任务已经加入调度,执行时此任务已经被删除", ex); }
说明,得到当前定时任务配置的数据方法如下:
JobDataMap data = context.getJobDetail().getJobDataMap();
这样做了之后,该定时任务就在下次启动时删除不会启动。
得到当前正在运行的普通定时任务(非后台)方法如下:
for (iter = runningJobs.iterator(); iter.hasNext();) { JobExecutionContext item = (JobExecutionContext) iter.next(); if ((item.getJobInstance() instanceof TaskRegJob)) { log.info("系统中有正在运行的任务,任务ID:" + item.getJobDetail().getJobDataMap() .getLongValue("TASK_ID") + ",执行类:" + item.getJobDetail().getJobClass().getName()); } }
总结:
本文所说的方法:主要是先配置一个后台定时任务扫描数据库,采用另一个定时任务以配置的时间间隔调用具体的方法达到动态配置定时任务的效果。
主要缺点如下:
1必须先配置一个后台定时任务。
2具体类实现抽象类,一个具体类一次只能配置一个定时任务,可以多次配置。也就是说定时任务的方法是固定的。
全文完,写的不好的地方请指教,有更好的方法请留言。
相关推荐
SpringBoot2 与 Quartz 整合的Demo。 后台可添加、修改、移除 定时任务。 也可查看当前任务的状态 灵活的定时任务
定时任务quartz实现分组串行并行动态配置
spring3 配置quartz定时任务的使用。一个小例子。可直接运行Test.java。就可以启动定时任务。每10秒钟执行一次,可以根据自己配置。
Quartz定时任务
quartz定时任务使用例子大全,这里面介绍了三种使用quartz定时任务的方式,第一种方式是完全使用代码写死的调用方式,第二种使用的是从数据库读取任务配置信息的调用方式,第三种是使用从数据库读取任务配置,生成...
Springboot整合Quartz实现定时任务数据库动态配置,新增任务、修改cron表达式、暂停任务、恢复任务、删除任务等操作
可以通过quartz和spring的简单配置即可完成,但如果要改变任务的执行时间、频率,废弃任务等就需要改变配置甚至代码需要重启服务器,这里介绍一下如何通过quartz与spring的组合实现动态的改变定时任务的状态的一个...
Spring + quartz 定时任务修改定时时间不重启服务
quartz 动态定时任务 根据数据库数据配置动态定时任务
ssm整合quartz 并持久化到数据库中,实现动态增删改查,暂停任务,恢复任务等 将链接内的target文件直接放到项目ssmquartztest文件夹下 运行环境: jdk5+tomcat7+mysql+eclipse+maven lib jar包下载地址 地址1:...
quartz定时
springboot+quartz 动态化配置,可在页面操作,查看、添加、修改、删除,暂停等操作
附件中实现了对quartz的动态添加、修改和删除定时任务,方便通过页面动态控制执行定时任务。
使用quartz实现的java 定时任务,通过写cron表达式,让任务在制定时刻触发执行。
spring3 配置quartz定时任务的使用。一个小例子。可直接运行Test.java。就可以启动定时任务。
Spring Boot 配置 Quartz 定时任务(csdn)————程序
spring-cloud-alibaba+dubbo+nacos+quartz以yml配置方式实现
Quartz定时任务常用的11张数据库脚本表结构,网上大部分都是只是说说,没有实际帮助,有的大部分积分还很贵,本人总结一下,希望能给有需要的人一些帮助。
Quartz定时任务框架,本次小白使用它实现一个简单的定时任务。每隔3秒打印一次Hello。这个是例子的jar包,实现过程在博客首页可看到。
Java Quartz定时任务简单列子