Quartz监听器和持久化

发布于 2022-10-19  1.66k 次阅读


1.Quartz监听器

   Quartz的监听器用于当前任务调度中你所关注事件发生时,能够及时获取这一事件的通知,类似于String AOP在事件执行前后运行相应的指定程序

Quartz监听器的三大类型:

  • JobListener:任务监听器
  • TriggerListener:触发器监听器
  • SchedulerListener:调度器监听器

三者的使用方法类似

监听器的分类:

  • 全局监听器:能够接收到所有的Job/Trigger的事件通知
  • 非全局监听器:只能接收到在其上注册的Job/Trigger事件,不在其注册不好监听

1.1 JobListener

任务调度过程中,与任务Job相关的事件包括:Job开始要执行的提示,Job执行完成的提示

JobListener接口源码:

public interface JobListener {
    String getName();

    void jobToBeExecuted(JobExecutionContext var1);

    void jobExecutionVetoed(JobExecutionContext var1);

    void jobWasExecuted(JobExecutionContext var1, JobExecutionException var2);
}
  • getName():用于获取该JobListener的名称
  • jobToBeExecuted:Scheduler在JobDetail将要被执行时调用这个方法
  • jobExecutionVetoed:Scheduler在JobDetail即将被执行,但又被TriggerListener否决时会调用该方法
  • jobWasExecuted:Scheduler在JobDetail被执行之后调用该方法

例:

① Job类

public class MyJobListerJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateformat = simpleDateFormat.format(date);


        System.out.println(dateformat+"--数据库备份!!");
    }
}

② Job监听器

public class MyJobListener implements JobListener {
    @Override
    public String getName() {
        String ListenerName = this.getClass().getSimpleName();
        return ListenerName;
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
        System.out.println("Job即将被执行时调用!!");
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
        System.out.println("Job即将被执行,但又被TriggerListener否决时调用!!");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
        System.out.println("Job被执行之后调用!!");
    }
}

③ Scheduler

Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();

JobDetail jobDetail = JobBuilder.newJob(MyJobListerJob.class)
        .withIdentity("job1", "group1")
        .build();

SimpleTrigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1")
        .startNow()
        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(2))//5秒执行一次,总共3次(从0开始)
        .build();

defaultScheduler.scheduleJob(jobDetail,trigger);

//创建注册一个全局的Job监听器
defaultScheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs());

//创建注册一个局部的Job监听器,指定任务Job
//defaultScheduler.getListenerManager().addJobListener(new MyJobListener(), KeyMatcher.keyEquals(JobKey.jobKey("job1","group1")));

defaultScheduler.start();

输出:

Job即将被执行时调用!!
2022-10-15 12:30:22--数据库备份!!
Job被执行之后调用!!
Job即将被执行时调用!!
2022-10-15 12:30:27--数据库备份!!
Job被执行之后调用!!

1.2 TriggerListener

任务调度过程中,与触发器Trigger相关的事件包括:触发器触发,触发器未正常触发,触发器完成等

TriggerLIstener接口源码:

public interface TriggerListener {
    String getName();


    void triggerFired(Trigger var1, JobExecutionContext var2);


    boolean vetoJobExecution(Trigger var1, JobExecutionContext var2);


    void triggerMisfired(Trigger var1);


    void triggerComplete(Trigger var1, JobExecutionContext var2, CompletedExecutionInstruction var3);
}
  • getName:获取用于触发器的名称
  • triggerFired:当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用执行该方法
  • vetoJobExecution:在Trigger触发后,Job将要被执行时由Scheduler调用这个方法。TriggerLIstener给了一个选择去否决Job的执行,假如这个方法返回true,这个job将不会为此Trigger触发而得到执行
  • triggerMisfired:Scheduler调用这个方法是在Trigger错过触发时,你应该关注此方法中持续时间长的逻辑;在出现许多错过触发的Trigger时,长逻辑会导致骨牌效验
  • triggerComplete:Trigger被触发并且完成了Job的执行时,Scheduler调用这个方法

例:

① TriggerListen

public class MyTriggenListener implements TriggerListener {
    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) {
        System.out.println("Trigger被触发!!");
    }

    @Override
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) {
        System.out.println("Job没有被触发!!");
        return true;//返回true JOB不会被执行
    }

    @Override
    public void triggerMisfired(Trigger trigger) {
        System.out.println("Trigger错过触发!!");
    }

    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) {
        System.out.println("Trigger完成之后被触发!!");
    }
}

② Scheduler

Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();

JobDetail jobDetail = JobBuilder.newJob(MyTriggerListenerJob.class)
        .withIdentity("job1", "group1")
        .build();

SimpleTrigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1")
        .startNow()
        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(2))//5秒执行一次,总共3次(从0开始)
        .build();

defaultScheduler.scheduleJob(jobDetail,trigger);

//创建注册一个全局的trigger监听器
defaultScheduler.getListenerManager().addTriggerListener(new MyTriggenListener(), EverythingMatcher.allTriggers());

//创建注册一个局部的trigger监听器,指定trigger的名称和组
//defaultScheduler.getListenerManager().addTriggerListener(new MyTriggenListener(), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger1","group1")));

defaultScheduler.start();

输出:

Trigger被触发!!
job没有被触发!
Trigger被触发!!
job没有被触发!

1.3 SchedulerListener

    SchedulerListener与TriggerListener、JobListener类似,但它仅接收来自Scheduler自身的消息,而不一定是某个具体的trigger或job的消息。

    Scheduler相关的消息包括:job/trigger的增加、job/trigger的删除、scheduler内部发生的严重错误以及scheduler关闭的消息等

SchedulerListener接口源码:

public interface SchedulerListener {
    public void jobScheduled(Trigger trigger);
    public void jobUnscheduled(String triggerName, String triggerGroup);
    public void triggerFinalized(Trigger trigger);
    public void triggersPaused(String triggerName, String triggerGroup);
    public void triggersResumed(String triggerName, String triggerGroup);
    public void jobsPaused(String jobName, String jobGroup);
    public void jobsResumed(String jobName, String jobGroup);
    public void schedulerError(String msg, SchedulerException cause);
    public void schedulerStarted();
    public void schedulerInStandbyMode();
    public void schedulerShutdown();
    public void schedulingDataCleared();
}
  • jobScheduled() 和 jobUnscheduled():Scheduler 在有新的 JobDetail 部署或卸载时调用这两个中的相应方法。
  • triggerFinalized() :当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设置成了持久性,否则它就会从 Scheduler 中移除。
  • triggersPaused():Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是 Trigger 组的话,triggerName 参数将为 null。
  • triggersResumed():Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是 Trigger 组的话,triggerName 参数将为 null。
  • jobsPaused():当一个或一组 JobDetail 暂停时调用这个方法。
  • jobsResumed():当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数将为 null。
  • schedulerError():在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法。
  • schedulerStarted():当scheduler开启时,调用该方法
  • schedulerShutdown():当Schenedler停止时调用
  • schedulingDataCleared():当Scheduler数据被清除时,调用该方法

例:

① MySchedulerListener

public class MySchedulerListener implements SchedulerListener {

    @Override
    public void jobScheduled(Trigger trigger) {
        System.out.println("MySchedulerListener jobScheduled trigger");
    }

    @Override
    public void jobUnscheduled(TriggerKey triggerKey) {
        System.out.println("MySchedulerListener jobScheduled triggerKey");
    }

    @Override
    public void triggerFinalized(Trigger trigger) {
       System.out.println("MySchedulerListener triggerFinalized");
    }

    @Override
    public void triggerPaused(TriggerKey triggerKey) {
        System.out.println("MySchedulerListener triggerPaused");
    }

    @Override
    public void triggersPaused(String triggerGroup) {
        System.out.println("MySchedulerListener triggersPaused");
    }

    @Override
    public void triggerResumed(TriggerKey triggerKey) {
        System.out.println("MySchedulerListener triggerResumed triggerKey");
    }

    @Override
    public void triggersResumed(String triggerGroup) {
        System.out.println("MySchedulerListener triggerResumed triggerGroup");

    }

    @Override
    public void jobAdded(JobDetail jobDetail) {
        System.out.println("MySchedulerListener jobAdded");
    }

    @Override
    public void jobDeleted(JobKey jobKey) {
        System.out.println("MySchedulerListener jobDeleted");

    }

    @Override
    public void jobPaused(JobKey jobKey) {
        System.out.println("MySchedulerListener jobPaused jobKey");

    }

    @Override
    public void jobsPaused(String jobGroup) {
        System.out.println("MySchedulerListener jobsPaused jobGroup");

    }

    @Override
    public void jobResumed(JobKey jobKey) {
        System.out.println("MySchedulerListener jobResumed  jobKey");

    }

    @Override
    public void jobsResumed(String jobGroup) {
        System.out.println("MySchedulerListener jobsResumed  jobGroup");

    }

    @Override
    public void schedulerError(String msg, SchedulerException cause) {
        System.out.println("MySchedulerListener schedulerError");

    }

    @Override
    public void schedulerInStandbyMode() {
        System.out.println("MySchedulerListener schedulerInStandbyMode");

    }

    @Override
    public void schedulerStarted() {
        System.out.println("MySchedulerListener schedulerStarted");

    }

    @Override
    public void schedulerStarting() {
        System.out.println("MySchedulerListener schedulerStarting");

    }

    @Override
    public void schedulerShutdown() {
        System.out.println("MySchedulerListener schedulerShutdown");

    }

    @Override
    public void schedulerShuttingdown() {
        System.out.println("MySchedulerListener schedulerShuttingdown");

    }

    @Override
    public void schedulingDataCleared() {
        System.out.println("MySchedulerListener schedulingDataCleared");
    }
}

② 调度

public class SchedulerListenerDemo {

    public static void main(String[] args) throws Exception {

        System.out.println("------- 初始化 ----------------------");

        // Scheduler
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

        // 添加监听器
        SchedulerListener schedulerListener = new MySchedulerListener();
        scheduler.getListenerManager().addSchedulerListener(schedulerListener);

        // Job
        JobDetail job = newJob(SimpleJob1.class).withIdentity("job1", "group1")
                .build();

        // Tirgger
        Trigger trigger = newTrigger().withIdentity("trigger1", "group1")
                .startNow().build();

        // 将job任务加入到调度器
        scheduler.scheduleJob(job, trigger);

        // 开始任务
        System.out.println("------- 开始执行调度器 Scheduler ----------------");
        scheduler.start();

        try {
            System.out.println("------- 等待 30 秒... --------------");
            Thread.sleep(30L * 1000L);
        } catch (Exception e) {
            e.printStackTrace();
        }

        scheduler.shutdown(true);
        System.out.println("------- 关闭调度器 -----------------");

        SchedulerMetaData metaData = scheduler.getMetaData();
        System.out.println("~~~~~~~~~~  执行了 "
                + metaData.getNumberOfJobsExecuted() + " 个 jobs.");
    }
}

输出:

MySchedulerListener jobAdded
MySchedulerListener jobScheduled trigger
------- 开始执行调度器 Scheduler ----------------
MySchedulerListener schedulerStarting
INFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
MySchedulerListener schedulerStarted
------- 等待 30 秒... --------------

Job1 - 任务key group1.job1执行时间:2017-11-16 22:14:33
MySchedulerListener triggerFinalized
MySchedulerListener jobDeleted
INFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
INFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
MySchedulerListener schedulerInStandbyMode
MySchedulerListener schedulerShuttingdown
MySchedulerListener schedulerShutdown
INFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
------- 关闭调度器 -----------------
~~~~~~~~~~  执行了 1 个 jobs.

2. Quartz任务持久化

2.1 Quartz Store概述

Quartz提供了两种不同类型的任务存储方式:

  1. 内存存储(默认)
  2. 数据库存储

这两种方式都是基于org.quartz.spi.JobStore接口来实现的

JobStore的实现类结构:

  • org.quartz.spi.JobStore 是任务存储的顶层接口类
  • org.quartz.simpl.RAMJobStore 是内存存储机制实现类
  • org.quartz.impl.jdbcjobstore.JobStoreSupport 是基于JDBC数据库存储的抽象类
  • org.quartz.impl.jdbcjobstore.JobStoreCMT 是受应用容器管理事务的数据库存储实现类
  • org.quartz.impl.jdbcjobstore.JobStoreTX 是不受应用容器事务管理的数据库存储实现类

    在项目开发中,我们无需调用JobStore实现类中的方法,只需配置即可,但是了解还是很有必要的,因为可以让我们在项目应用中选择更加适合的存储类型(内存/数据库/文件)

2.2 JobStrore接口实现类

2.2.1 RAMJobstore内存存储任务

Quartz默认的存储机制就是使用内存进行存储的

Quartz的jar包中的默认配置文件quartz.properties:

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

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

 主要看org.quartz.jobStore.class这个属性,属性值org.quartz.simpl.RAMJobStore就是内存存储机制的实现类。如果需要使用别的存储机制,那就将此值替换为别的实现类即可

    使用内存存储的优点是任务的存储和读取的速度极快,和数据库持久化相比差别还是非常大的,而且框架搭建简单,开箱即用。它的缺点是当Quartz程序或应用程序停止了,伴随在内存中的数据也会被回收,任务等数据就永久丢失了

  使用内存存储时,注意配置文件中只需要保留基本的线程池配置和jobStore的实现类等几个简单的属性就行。如果使用了实现类中没有的属性,启动的时候会报错

2.2.2 数据库存储数据

    JobStoreTX和JobStoreCMT都是JobStoreSupport抽象类的实现类,JobStoreSupport是基于JDBC实现了一些基本的功能的抽象类。如果想要自己实现一套关于JDBC存储方式,那么可以继承此抽象类

Quartz支持的数据库:

  • Oracle
  • MySQL
  • Microsoft SQL Server
  • HSQLDB
  • PostgreSQL
  • DB2
  • Cloudscape/Derby
  • Pointbase
  • Informix
  • Firebird
  • ……

quartz官网:http://www.quartz-scheduler.org/downloads/

Quartz的数据库表结构: 在quartz官网下载quartz文件,然后解压文件,找到其中的sql文件。quartz2.4.0版本的sql路径为:\quartz-2.4.0-SNAPSHOT\src\org\quartz\impl\jdbcjobstore

quartz持久化各个表的含义:

表名 含义
QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息
QRTZ_CRON_TRIGGERS 存储CronTrigger触发器信息,包括Cron表达式和时区等信息
QRTZ_FIRED_TRIGGERS 存储已触发的Trigger状态信息和关联的Job执行信息
QRTZ_PAUSED_TRIGGER_GRPS 存储已暂停的Trigger组信息
QRTZ_SCHEDULER_STATE 存储有关Scheduler的状态信息
QRTZ_LOCKS 存储程序锁信息
QRTZ_JOB_DETAILS 存储Job的详细信息
QRTZ_JOB_LISTENERS 存储Job配置的JobListener信息
QRTZ_SIMPLE_TRIGGERS 存储SimpleTrigger触发器信息,包括重复次数,间隔等信息
QRTZ_BLOG_TRIGGERS 存储Blob类型的Trigger,一般用于自定义触发器
QRTZ_TRIGGER_LISTENERS 存储已配置的TriggerListener信息
QRTZ_TRIGGERS 存储已配置的Trigger的信息

表的前缀可以在quartz.properties中进行自定义配置,假如在项目中需要两套调度器实例,要分别持久化两套job信息,此时就可以自定义前缀进行区分:

org.quartz.jobStore.tablePrefix=QRTZ1_
org.quartz.jobStore.tablePrefix=QRTZ2_
QRTZ1_ 和QRTZ2_分别是两套表的前缀,分别配置在不同的quartz.properties中,然后根据两个配置文件分别初始化调度实例

2.2.3 JobStoreTX

    TX就是事务的意思,此存储机制用于Quartz独立于应用容器的事务管理,如果是Tomcat容器管理的数据源,那我们定义的事务也不会传播给Quartz框架内部。通俗的讲就是不管我们的Service服务本身业务代码是否执行成功,只要代码中调用了Quartz API的数据库操作,那任务状态就永久持久化了,就算业务代码抛出运行时异常任务状态也不会回滚到之前的状态

JobStoreTX的配置:

1)配置org.quartz.jobStroe.class属性

org.quartz.jobStore.class= org.quartz.impl.jdbcjobstore.JobStoreTX

2)配置驱动代理,以MySQL为例

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

3)配置数据源

org.quartz.jobStore.dataSource=qzDS
org.quartz.dataSource.qzDS.driver= com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL= jdbc:mysql://localhost:3306/testDB
org.quartz.dataSource.qzDS.user= root
org.quartz.dataSource.qzDS.password= admin
org.quartz.dataSource.qzDS.maxConnection= 20

   列出一个可用的数据库代理类表格,方便大家使用,如果表格中没有列出你想要的代理类,那就使用标准的 JDBC 代理:org.quartz.impl.jdbcjobstore.StdDriverDelegate

数据库平台 Quartz 代理类
Cloudscape/Derby org.quartz.impl.jdbcjobstore.CloudscapeDelegate
DB2 (version 6.x) org.quartz.impl.jdbcjobstore.DB2v6Delegate
DB2 (version 7.x) org.quartz.impl.jdbcjobstore.DB2v7Delegate
DB2 (version 8.x) org.quartz.impl.jdbcjobstore.DB2v8Delegate
HSQLDB org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
Oracle org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
MS SQL Server org.quartz.impl.jdbcjobstore.MSSQLDelegate
Pointbase org.quartz.impl.jdbcjobstore.PointbaseDelegate
PostgreSQL org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
(WebLogic JDBC Driver) org.quartz.impl.jdbcjobstore.WebLogicDelegate
(WebLogic 8.1 with Oracle) org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate

注:

  • org.quartz.dataSource.qzDS.URL属性名末尾的URL字符串必须是大写,如果写成org.quartz.dataSource.qzDS.url ,那初始化调度实例时就会报错
  • org.quartz.jobStore.dataSource属性,这个属性的意思是给数据源起一个名字。这里属性值配置的是“qzDS”,你也可以配置成别的任意字符串,比如:“abc”,如果真这么做,那就需要将org.quartz.dataSource.qzDS.driver和其他配置的“qzDS”更换为“abc”,配置:
org.quartz.jobStore.dataSource=abc
org.quartz.dataSource.abc.driver= com.mysql.jdbc.Driver
org.quartz.dataSource.abc.URL= jdbc:mysql://localhost:3306/testDB
org.quartz.dataSource.abc.user= root
org.quartz.dataSource.abc.password= admin
org.quartz.dataSource.abc.maxConnection= 20

那么Quartz为什么设计要org.quartz.jobStore.dataSource属性呢?

  这个属性主要的目的就是在同一个数据库中需要使用多套Quartz,一般大家只需要一套数据源就可以完成业务工作,除非有一些特别的需求。比如SaaS模式下可以对不同公司的任务调度进行管理等。

提供一个完整job持久化的配置文件,该一下数据源、用户名和密码即可:

org.quartz.scheduler.instanceName=DefaultQuartzScheduler

org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5
org.quartz.jobStore.misfireThreshold=60000

org.quartz.jobStore.class= org.quartz.impl.jdbcjobstore.JobStoreTX

org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate

org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.dataSource=qzDS

org.quartz.dataSource.qzDS.driver= com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL= jdbc:mysql://localhost:3306/testDB
org.quartz.dataSource.qzDS.user= root
org.quartz.dataSource.qzDS.password= admin
org.quartz.dataSource.qzDS.maxConnection= 20

2.2.4 JobStoreCMT

    CMT的全称是Container Managed Transactions,表示容器管理事务,也就是让应用容器托管事务。这里假设应用容器是Tomcat,并且项目和Quartz都是使用Tomcat配置的数据源,那么项目和Quartz的代码中就可以共用同一个事务,不管是业务代码还是Quartz内部抛出异常,Service服务内的所有数据操作都会回滚到原始状态

JobStoreCMT和JobStoreTX最大的区别 是JobStoreCMT需要配置两个数据源,一个是受应用容器管理的数据源,还有一个是不受应用容器管理的数据源

JobStoreCMT的配置:

1)配置org.quartz.jobStroe.class属性

2)配置驱动代理,以Mysql为例,其它代理类参考上面表格

3)配置两个数据源

① 配置不受应用容器管理的数据源

org.quartz.jobStore.nonManagedTXDataSource = qzDS
org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/testDB
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = admin
org.quartz.dataSource.qzDS.maxConnections = 10

nonManagedTXDataSource就是非管理事务数据源的意思

② 配置受应用容器管理的数据源

org.quartz.dataSource.dataSource=myDS
org.quartz.dataSource.jndiURL = jdbc/mysql
org.quartz.dataSource.myDS.jndiAlwaysLookup = DB_JNDI_ALWAYS_LOOKUP
org.quartz.dataSource.myDS.java.naming.factory.initial = org.apache.naming.java.javaURLContextFactory
org.quartz.dataSource.myDS.java.naming.provider.url = http://localhost:8080
org.quartz.dataSource.myDS.java.naming.security.principal = root
org.quartz.dataSource.myDS.java.naming.security.credentials = admin

受应用容器管理的数据源配置属性的含义:

  • org.quartz.dataSource.NAME.jndiURL:受应用服务器管理的DataSource的JNDI URL
  • org.quartz.dataSource.NAME.java.naming.factory.initial:JNDI InitialContextFactory的类名称
  • org.quartz.dataSource.NAME.java.naming.provider.url:连接到JNDI的URL
  • org.quartz.dataSource.NAME.java.naming.security.principal:连接到 JNDI 的用户名
  • org.quartz.dataSource.NAME.java.naming.security.credential:连接到 JNDI 的用户凭证密码

选择:

  • JobStoreCMT在实际开发的过程中我还没有在项目中使用过此种方式,一般情况下都是使用的JobStoreTX,如果大家的项目中有着严格的事务管理,那么建议使用JobStoreCMT存储方式

路漫漫其修远兮,吾将上下而求索