quartz持久化到mysql报错_【Quartz】持久化到数据库【五】

本文介绍了如何将Quartz定时任务持久化到MySQL数据库,以确保任务在异常情况后能继续执行。文章讲解了Quartz任务的有状态和无状态概念,并提供了数据库表结构和SQL脚本。通过示例代码展示了配置数据库存储的步骤,以及如何创建有状态和无状态任务。最后,文中包含了调度器和调度工厂的使用方法,以及测试运行的示例。
摘要由CSDN通过智能技术生成

前言

我们做到这里已经对Quartz定时器组件已经是学会了基本的使用了。但是我们有没有想过任务开启之后万一断掉了,当机了我们怎么办,你是否还想继续执行原先的任务。我们普通的创建是把任务放在内存中存储,如果内存被释放掉,任务也就消失了,那怎么办哪,不得不说这个组件还是很厉害的。他已经帮我们想过了解方案---就是放到数据库。

Quartz插一嘴:

quartz在任务中分为两种:有状态和无状态执行。

有状态:对于同一个 trigger 来说,有状态的 job 不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。所有我自己理解为串行的顺序执行(自己怎么好记怎么理解 哈哈)

无状态:无状态任务一般指可以并发的任务,即任务之间是独立的,不会互相干扰。就是各自干各自的。

数据库概貌:

首先上一下sql脚本下载地址:sql数据库rar文件下载

表结构瞅一瞅:

AAffA0nNPuCLAAAAAElFTkSuQmCC

下面是表代表的大致意思吧:

表名描述QRTZ_BLOB_TRIGGERS作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候)

QRTZ_CALENDARS以 Blob 类型存储 Quartz 的 Calendar 信息

QRTZ_CRON_TRIGGERS存储 Cron Trigger,包括 Cron 表达式和时区信息

QRTZ_FIRED_TRIGGERS存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息

QRTZ_JOB_DETAILS存储每一个已配置的 Job 的详细信息

QRTZ_LOCKS存储程序的非观锁的信息(假如使用了悲观锁)

QRTZ_PAUSED_TRIGGER_GRPS存储已暂停的 Trigger 组的信息

QRTZ_SCHEDULER_STATE存储少量的有关 Scheduler 的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)

QRTZ_SIMPLE_TRIGGERS存储简单的 Trigger,包括重复次数,间隔,以及已触的次数

QRTZ_SIMPROP_TRIGGERS

QRTZ_TRIGGERS存储已配置的 Trigger 的信息

代码部分:

工具都有了那就干活吧,既然我上面说了任务分为有状态和无状态,那正好借这个例子一起给介绍一下。首先还是我们的老朋友任务的创建:

这是一个无状态任务

AAffA0nNPuCLAAAAAElFTkSuQmCCpublic class ServerJob : IJob

{        private const string Count = "count";        public virtual void Execute(IJobExecutionContext context)

{

JobKey jobKey = context.JobDetail.Key;            try

{                // 如果任务是恢复的任务的话

if (context.Recovering)

{

WritTxt.WriteFile("serversql", jobKey+":恢复打印");

}                else

{

WritTxt.WriteFile("serversql", jobKey+":启动打印");

}

JobDataMap data = context.JobDetail.JobDataMap;                int count;                if (data.ContainsKey(Count))

{

count = data.GetInt(Count);

}                else

{

count = 0;

}

count++;

data.Put(Count, count);

WritTxt.WriteFile("serversql", string.Format("结束: {0} done at {1}\n 累计数 #{2}", jobKey, DateTime.Now.ToString("r"), count));

}            catch (Exception ex)

{

}

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

下面是一个有状态任务,因为本人比较懒所有就不写新任务了,直接继承了无状态任务事件。[PersistJobDataAfterExecution] //代表当前任务是否有状态

[DisallowConcurrentExecution]//代表任务不允许并发

public class ServerJobState : ServerJob

{

}

下面就是我们要说的重点了;数据库配置

只需要在实例化调度器前把我们的数据库配置传进去就好了。

AAffA0nNPuCLAAAAAElFTkSuQmCC/// 

/// 持久化属性        /// 

NameValueCollection properties = new NameValueCollection();        public ExampleServer()

{

properties["quartz.scheduler.instanceName"] = "TestScheduler";

properties["quartz.scheduler.instanceId"] = "instance_one";

properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";

properties["quartz.threadPool.threadCount"] = "5";

properties["quartz.threadPool.threadPriority"] = "Normal";

properties["quartz.jobStore.misfireThreshold"] = "60000";

properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";

properties["quartz.jobStore.useProperties"] = "false";

properties["quartz.jobStore.dataSource"] = "default";

properties["quartz.jobStore.tablePrefix"] = "QRTZ_";

properties["quartz.jobStore.clustered"] = "true";

properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";

properties["quartz.dataSource.default.connectionString"] = "Server=(local);Database=quartz;Trusted_Connection=True;";

properties["quartz.dataSource.default.provider"] = "SqlServer-20";            // First we must get a reference to a scheduler

ISchedulerFactory sf = new StdSchedulerFactory(properties);

Scheduler = sf.GetScheduler();

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

然后就是运行测试了,这里我用了不同的形式返回了调度器和调度工厂。这样子也挺好用的,可以把以前的那种方法改成这种。

AAffA0nNPuCLAAAAAElFTkSuQmCC/// 

/// 调度工厂        /// 

private static StdSchedulerFactory SchedulerFactory { get; set; }        /// 

/// 调度接口        /// 

private static IScheduler Scheduler { get; set; }        #region 0.测试        public void Run()

{            string schedId = Scheduler.SchedulerInstanceId;

IJobDetail job = JobBuilder.Create()

.WithIdentity("ServerJob", schedId)

.RequestRecovery()

.Build();

ITrigger trigger = TriggerBuilder.Create()

.WithIdentity("serverTrigger", schedId)

.WithCronSchedule("0/10 * * * * ?")     //5秒执行一次                                          .Build();            //已存在就不重复添加

try

{

Scheduler.ScheduleJob(job, trigger);

}            catch (Exception ex)

{

}

IJobDetail jobState = JobBuilder.Create()

.WithIdentity("ServerJobSatte", schedId)

.RequestRecovery()

.Build();

ITrigger triggerState = TriggerBuilder.Create()

.WithIdentity("serverTriggerSatte", schedId)

.WithCronSchedule("0/10 * * * * ?")     //5秒执行一次                                          .Build();            //已存在就不重复添加

try

{

Scheduler.ScheduleJob(jobState, triggerState);

}            catch (Exception ex)

{

}            //启动            Scheduler.Start();

}        #endregion

AAffA0nNPuCLAAAAAElFTkSuQmCC

最后就是大结局了,让我们看下运行结果吧:

AAffA0nNPuCLAAAAAElFTkSuQmCC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值