Quartz2.2.1-JAVA-任务持久存储(MYSQL)

一:简介

Quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,第二种类型叫做JDBC作业存储。在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。
比如我们希望安排一个执行100次的任务,如果执行到50次时系统崩溃了,系统重启时任务的执行计数器将从0开始。在大多数实际的应用中,我们往往并不需要保存任务调度的现场数据,因为很少需要规划一个指定执行次数的任务。对于仅执行一次的任务来说,其执行条件信息本身应该是已经持久化的业务数据(如锁定到期解锁任务,解锁的时间应该是业务数据),当执行完成后,条件信息也会相应改变。当然调度现场信息不仅仅是记录运行次数,还包括调度规则、JobDataMap中的数据等等。
如果确实需要持久化任务调度信息,Quartz允许你通过调整其属性文件,将这些信息保存到数据库中。使用数据库保存任务调度信息后,即使系统崩溃后重新启动,任务的调度信息将得到恢复。如前面所说的例子,执行50次崩溃后重新运行,计数器将从51开始计数。使用了数据库保存信息的任务称为持久化任务。

二:资料

1.http://pan.baidu.com/s/1cqyCc2 里面包含该文档的demo 和quartz文档

三:开始

1.创建maven project项目:quartzDemo
2.创建数据库:quartzdb

          在资料文档中找到demo+quartz资料\quartz-2.2.1\docs\dbTables相应的数据库(我用的tables_mysql_innodb.sql ) ,如果报错检查一下,其中有一个地方写错了。改成与其他表相同即可。

创建成功后为(表结构请参照其他文档):

这里写图片描述

3.引入maven文件:(我用mysql,引入得是mysql驱动包)

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

4.创建项目后结构如下:
这里写图片描述

quartz.properties
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
#集群配置
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure JobStore
#============================================================================
#默认配置,数据保存到内存
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
#持久化配置
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties:true
#数据库表前缀
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS

#============================================================================
# Configure Datasources
#============================================================================
#JDBC驱动
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartzdb
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:123456
org.quartz.dataSource.qzDS.maxConnection:10

其中org.quartz.jobStore.class是指明quartz的持久化用数据库来保存,
而org.quartz.jobStore.driverDelegateClass是根据选择的数据库类型不同而不同,我这里的是mysql,所以是org.quartz.impl.jdbcjobstore.StdJDBCDelegate。
Quartz的属性配置文件主要包括三方面的信息:
1)集群信息;
2)调度器线程池;
3)任务调度现场数据的保存。
·调度器属性
第一部分有两行,分别设置调度器的实例名(instanceName) 和实例 ID (instanceId)。属性 org.quartz.scheduler.instanceName 可以是你喜欢的任何字符串。它用来在用到多个调度器区分特定的调度器实例。多个调度器通常用在集群环境中。现在的话,设置如下的一个字符串就行:org.quartz.scheduler.instanceName :DefaultQuartzScheduler实际上,这也是当你没有该属性配置时的默认值。
调度器的第二个属性是 org.quartz.scheduler.instanceId。和 instaneName 属性一样,instanceId 属性也允许任何字符串。这个值必须是在所有调度器实例中是唯一的,尤其是在一个集群当中。假如你想 Quartz 帮你生成这个值的话,可以设置为 AUTO。如果 Quartz 框架是运行在非集群环境中,那么自动产生的值将会是 NON_CLUSTERED。假如是在集群环境下使用 Quartz,这个值将会是主机名加上当前的日期和时间。大多情况下,设置为 AUTO 即可。
·线程池属性
接下来的部分是设置有关线程必要的属性值,这些线程在 Quartz 中是运行在后台担当重任的。threadCount 属性控制了多少个工作者线程被创建用来处理 Job。原则上是,要处理的 Job 越多,那么需要的工作者线程也就越多。threadCount 的数值至少为 1。Quartz 没有限定你设置工作者线程的最大值,但是在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下。这项没有默认值,所以你必须为这个属性设定一个值。
threadPriority 属性设置工作者线程的优先级。优先级别高的线程比级别低的线程更优先得到执行。threadPriority 属性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1。这个属性的正常值是 Thread.NORM_PRIORITY,为5。大多情况下,把它设置为5,这也是没指定该属性的默认值。
最后一个要设置的线程池属性是 org.quartz.threadPool.class。这个值是一个实现了 org.quartz.spi.ThreadPool 接口的类的全限名称。Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool,它能够满足大多数用户的需求。这个线程池实现具备简单的行为,并经很好的测试过。它在调度器的生命周期中提供固定大小的线程池。你能根据需求创建自己的线程池实现,如果你想要一个随需可伸缩的线程池时也许需要这么做。这个属性没有默认值,你必须为其指定值。
·作业存储设置
作业存储部分的设置描述了在调度器实例的生命周期中,Job 和 Trigger 信息是如何被存储的。我们还没有谈论到作业存储和它的目的;因为对当前例子是非必的,所以我们留待以后说明。现在的话,你所要了解的就是我们存储调度器信息在内存中而不是在关系型数据库中就行了。
把调度器信息存储在内存中非常的快也易于配置。当调度器进程一旦被终止,所有的 Job 和 Trigger 的状态就丢失了。要使 Job 存储在内存中需通过设置 org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore。假如我们不希望在 JVM 退出之后丢失调度器的状态信息的话,我们可以使用关系型数据库来存储这些信息。这需要另一个作业存储(JobStore) 实现,我们在后面将会讨论到。第五章“Cron Trigger 和其他”和第六章“作业存储和持久化”会提到你需要用到的不同类型的作业存储实现。

QuartzTest.java
package com.test.quartzDemo;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.core.jmx.JobDetailSupport;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.SimpleTriggerImpl;
/**
 * 
 * @author weishuai
 *
 */
public class QuartzTest {

    private static SchedulerFactory sf = new StdSchedulerFactory();
    private static String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_NAME";

    /**
     * 添加任务
     * 
     * @param jobName
     *            任务名称
     * @param job
     *            任务处理类 需要继承Job
     * @param context
     *            处理任务可以获取的上下文
     *            通过context.getMergedJobDataMap().getString("context"); 获取
     * @param seconds
     *            间隔秒
     * @return 0 添加成功 1:任务已经存在 2:添加异常
     */
    public static int addJob(String jobName, Class<? extends Job> job, Object task, int seconds, String jobGorupName) {
        try {
            // 判断任务是否存在
            Scheduler sche = sf.getScheduler();
            JobKey jobKey = JobKey.jobKey(jobName, jobGorupName);
            if (sche.checkExists(jobKey)) {
                return 1;// 任务已经存在
            }
            // 创建一个JobDetail实例,指定SimpleJob
            Map<String, Object> JobDetailmap = new HashMap<String, Object>();
            JobDetailmap.put("name", jobName);// 设置任务名字
            JobDetailmap.put("group", jobGorupName);// 设置任务组
            JobDetailmap.put("jobClass", job.getCanonicalName());// 指定执行类
                                                                    // Task.class.getCanonicalName()
            JobDetail jobDetail = JobDetailSupport.newJobDetail(JobDetailmap);
            // 添加数据内容
            jobDetail.getJobDataMap().put("task", task);// 传输的上下文
            // 通过SimpleTrigger定义调度规则:马上启动,每2秒运行一次,共运行100次 等。。。。
            SimpleTriggerImpl simpleTrigger = new SimpleTriggerImpl();
            simpleTrigger.setName(jobName);
            simpleTrigger.setGroup(TRIGGER_GROUP_NAME);
            // 什么时候开始执行
            simpleTrigger.setStartTime(new Date(new Date().getTime() + 1000 * seconds));
            // 间隔时间
            simpleTrigger.setRepeatInterval(1000 * seconds);
            // 最多执行次数 默认执行一次
            simpleTrigger.setRepeatCount(0);
            // 通过SchedulerFactory获取一个调度器实例
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.scheduleJob(jobDetail, simpleTrigger);// ④ 注册并进行调度
            scheduler.start();// ⑤调度启动
            return 0;// 添加成功
        } catch (Exception e) {
            // e.printStackTrace();
            return 2;// 操作异常
        }
    }
/**
     * 关闭任务调度
     * @param jobName 任务名称
     * @return 0 关闭成功 1: 关闭失败 2:操作异常
     */
    public static int closeJob(String jobName,String jobGorupName){
        //关闭任务调度
        try {
            Scheduler sche = sf.getScheduler();
            JobKey jobKey = JobKey.jobKey(jobName,jobGorupName);
            return sche.deleteJob(jobKey)==true?0:1;
        } catch (SchedulerException e) {
            //e.printStackTrace();
            return 2;
        }
    }
    public static void main(String[] args) throws SchedulerException, ParseException {
        // System.out.println(addJob("张科3", MyJob.class, "我是你的人", 10, "aaa"));
        //resumeJob();
    }

    /**
     * 从数据库中找到已经存在的job,并重新开始调度
     */
    public static void resumeJob() {
        try {
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.start();
        } catch (Exception e) {
            e.printStackTrace();

        }
    }
}
MyJob.java
package com.test.quartzDemo;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
 * 任务实现类
 * @author weishuai
 *
 */
public class MyJob implements Job{
    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        System.out.println(context.getMergedJobDataMap().get("task")+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date()));

    }

}

main方法中调用两个方法,第一个方法为添加任务 ,第二个方法为项目结束进程后在数据库中读取任务并放入进程。

添加成功后在数据库中看到:
这里写图片描述

原文请参照:http://blog.csdn.net/qq_30097433/article/category/6774980

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值