SSM整合Quartz框架

1.Quartz概述

Quartz是一款开源的优秀任务调度框架,易上手使用简单

运行环境

  • Quartz 可以运行嵌入在另一个独立式应用程序
  • Quartz 可以在应用程序服务器(或servlet容器)内被实例化,并且参与XA事务
  • Quartz 可以作为一个独立的程序运行(其自己的Java虚拟机内),可以通过RMI使用
  • Quartz 可以被实例化,作为独立的项目集群(负载平衡和故障转移功能),用于作业的执行

作业调度

作业被安排在一个给定的触发时运行。触发器可以使用以下指令的接近任何组合来创建:

  • 在一天中的某个时间(到毫秒)
  • 在一周的某几天
  • 在每月的某一天
  • 在一年中的某些日期
  • 不在注册的日历中列出的特定日期(如商业节假日除外)
  • 重复特定次数
  • 重复进行,直到一个特定的时间/日期
  • 无限重复
  • 重复的延迟时间间隔 作业是由其创建者赋予的名字,也可以组织成命名组。触发器也可以给予名称和放置在组中,以方便地将它们调度内组织。作业可以被添加到所述调度器一次,而是具有多个触发器注册。在企业Java环境中,作业可以执行自己的工作作为分布式(XA)事务的一部分。

作业执行

  • 作业可以实现简单的作业接口,为作业执行工作的任何Java类。
  • Job类的实例可以通过Quartz被实例化,或者通过应用程序框架。
  • 当触发时,调度通知实现JobListener和TriggerListener接口零个或多个Java对象(监听器可以是简单的Java对象,或EJB,JMS或发布者等)。这些监听器在作业已经执行之后通知。
  • 由于作业完成后返回JobCompletionCode,它通知的成功或失败的调度。JobCompletionCode还可以指示的基础上,成功的话就采取行动调度/失败的代码 - 如立即重新执行作业。

作业持久性

  • Quartz的设计包括可被实现以提供的作业存储各种机制一个作业存储接口
  • 通过使用包含的JDBCJobStore,所有的作业和触发器配置为“非挥发性”都存储在通过JDBC关系数据库。
  • 通过使用包含的RAMJobStore,所有的作业和触发器存储在RAM,因此不计划执行仍然存在 - 但这是无需使用外部数据库的优势。

事务

  • 可以参与JTA事务,通过使用JobStoreCMT(JDBCJobStore的子类)。 Quartz可以管理JTA事务(开始并提交它们)周围作业的执行,从而使作业执行的工作自动将JTA事务中发生。 集群 故障切换 负载均衡 Quartz的内置的群集功能,通过JDBCJobStore(如上所述)依靠数据库持久 Terracotta扩展Quartz提供集群功能,而不需要一个支持数据库 监听器和插件 应用程序可以捕捉事件的调度监控或通过实现一个或多个监听器接口控制工作/触发行为。 插件机制,可以用来添加功能,Quartz让作业执行过程中或工作负载和触发定义的历史不受限在一个文件中。 附带了一些“工厂建有”插件和监听器。

Quartz核心组件

组件描述
Job

是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在 JobDataMap实例中。

JobDetail

Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。

Trigger

是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等。

Calendar

org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。

Scheduler

代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在 Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。

ThreadPool

Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。

JobDataMap

是一个Map的实现,用于存储Job中所需用到的数据

JobStore

用于将Job和Trigger信息存储,以便Scheduler再次恢复使用。常用子类:JobStoreCMT, JobStoreTX,RAMJobStore

2.持久化方式选择



 

  • JDBC方式持久化 

     

3.配置文件applicationContext-qaurtz.xml的编写

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

   <!-- =========JDBC版=========== -->
   <!--
       持久化数据配置,需要添加quartz.properties
    -->
   <bean id="quartzDataSource" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="${quartz.driver}"/>
      <property name="url" value="${quartz.url}"/>
      <property name="username" value="${quartz.username}"/>
      <property name="password" value="${quartz.password}"/>
      <property name="initialSize" value="${quartz.initialSize}"/>
      <property name="maxActive" value="${quartz.maxActive}"/>
      <property name="maxIdle" value="${quartz.maxIdle}"/>
      <property name="minIdle" value="${quartz.minIdle}"/>
      <property name="maxWait" value="${quartz.maxWait}"/>
   </bean>

   <!-- spring对quartz的整合所提供的SchedulerFactory -->
   <bean name="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
      <property name="dataSource" ref="quartzDataSource"/>
      <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>

      <!-- configLocation属性,通过读取quartz.properties配置文件初始化Scheduler -->
      <property name="configLocation" value="classpath:properties/quartz.properties"/>
   </bean>
</beans>

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.
#

#============================================================================
# Configure Main Scheduler Properties   (Qaurtz调度器的主要属性配置)
#============================================================================
org.quartz.scheduler.instanceName: dufy_test
org.quartz.scheduler.instanceId = AUTO

org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
#============================================================================
# Configure ThreadPool                  (Quartz的线程池配置)
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 1
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure JobStore                    (Quartz任务存储的配置,采用jdbc持久化存储方式)
#============================================================================

#default config
#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.PostgreSQLDelegate
#org.quartz.jobStore.useProperties:true


#数据库表前缀
org.quartz.jobStore.tablePrefix:qrtz_
#org.quartz.jobStore.dataSource:qzDS

#============================================================================
#havent cluster spring                  (Quartz集群配置,不采用集群方式)
#============================================================================
org.quartz.jobStore.isClustered = false

#============================================================================
# Configure Datasources                 (Quartz数据源的配置,无需配置独立的数据源,采用已配置的dbcp连接池)
#============================================================================
##JDBC驱动
#org.quartz.dataSource.qzDS.driver:org.postgresql.Driver
#org.quartz.dataSource.qzDS.URL:jdbc:postgresql://127.0.0.1:5432/postgres
#org.quartz.dataSource.qzDS.user:postgres
#org.quartz.dataSource.qzDS.password:111
#org.quartz.dataSource.qzDS.maxConnection:10

5.Qaurtz的各种操作的使用示例

(1)Qaurtz中Job的编写

public class HelloWordJob implements Job {

    private static final Logger logger = LoggerFactory.getLogger(HelloWordJob.class);

    //execute()方法中为job所执行的任务逻辑
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("This is a first spring combine quartz !");
        logger.info("Welcome to Spring_Quartz World!"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) );
        logger.info("Let's begin ! \n \n");
    }
}

(2)新建添加任务

//(1)创建JobDetail实例
JobDetail jobDetail=JobBuilder.newJob(HelloWordJob.class)
        .withIdentity("job005","group005")
        .build();
//(2)创建Trigger实例
Trigger trigger=TriggerBuilder.newTrigger()
        .withIdentity("job005","group005")
        .startNow()
        .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
        .build();
//(3)开启scheduler,执行任务,关闭scheduler
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
Thread.sleep(10*1000L);
scheduler.shutdown(true);

(3)将数据传送到任务

JobDataMap jobDataMap=new JobDataMap();
jobDataMap.put("name","Wu Menghao");
//(1)创建JobDetail实例
JobDetail jobDetail=JobBuilder.newJob(DataMapJob.class)
        .usingJobData(jobDataMap)
        .withIdentity("job001","group001")
        .build();
//(2)创建Trigger实例
Trigger trigger=TriggerBuilder.newTrigger()
        .withIdentity("trigger001","group001")
        .startNow()
        .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
        .build();
//(3)开启scheduler,执行任务,关闭scheduler
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
Thread.sleep(10*1000L);
scheduler.shutdown(true);

(4)任务绑定多个触发器

JobDataMap jobDataMap=new JobDataMap();
jobDataMap.put("name","job002");
//Job
JobDetail jobDetail=JobBuilder.newJob(DataMapJob.class)
        .usingJobData(jobDataMap)
        .withIdentity("job002","group002")
        .build();
//Triggers
Set<Trigger> triggers=new HashSet<>();
Trigger trigger1=TriggerBuilder.newTrigger()
        .withIdentity("trigger001","group002")
        .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
        .build();
Trigger trigger2=TriggerBuilder.newTrigger()
        .withIdentity("trigger002","group002")
        .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))
        .build();
triggers.add(trigger1);
triggers.add(trigger2);
//scheduleJob
scheduler.scheduleJob(jobDetail,triggers,false);
scheduler.start();
Thread.sleep(60*1000L);
scheduler.shutdown();

(5)任务的暂停与恢复

任务暂停后恢复,任务会继续按触发器的规则执行

//暂停
scheduler.pauseJob(JobKey.jobKey("job004","group004"));
scheduler.pauseJob(JobKey.jobKey("job005","group005"));
Thread.sleep(5*1000L);
System.out.println("停止5s");

//恢复(按照trigger执行)
scheduler.resumeJob(JobKey.jobKey("job005","group005"));
scheduler.start();
Thread.sleep(60*1000L);
scheduler.shutdown();

(6)任务的暂停与立执行

任务暂停后立即执行,任务仅执行一次

//暂停
scheduler.pauseJob(JobKey.jobKey("job004","group004"));
scheduler.pauseJob(JobKey.jobKey("job005","group005"));
Thread.sleep(5*1000L);
System.out.println("停止5s");

//立即执行(仅执行一次)
scheduler.triggerJob(JobKey.jobKey("job005","group005"));
scheduler.start();
Thread.sleep(60*1000L);
scheduler.shutdown();

(7)任务的删除--暂停-解绑-删除

TriggerKey triggerKey = TriggerKey.triggerKey("job003","group003");
JobKey jobKey=JobKey.jobKey("job003","group003");
//(1)暂停触发器
scheduler.pauseTrigger(triggerKey);
//(2)解除触发器
scheduler.unscheduleJob(triggerKey);
//(3)删除任务
scheduler.deleteJob(jobKey);
scheduler.shutdown();

(8)任务的删除--直接删除

JobKey jobKey=JobKey.jobKey("job002","group002");
scheduler.deleteJob(jobKey);
scheduler.shutdown();
System.out.println(scheduler.isShutdown());
Thread.sleep(60*1000L);

(9)暂停触发器与暂停任务

  • 暂停触发器与暂停任务都能使任务暂停,都能通过resumeJobe()方法恢复

  • 一个任务可以绑定多个触发器,pauseTrigger只能暂停指定的Trigger,puaseJob可以暂停所有的Trigger

    @Test
    public void pauseTrigger() throws SchedulerException, InterruptedException {
        //暂停触发器
        scheduler.pauseTrigger(TriggerKey.triggerKey("trigger001","group002"));
        Thread.sleep(60*1000L);
    }
    
    @Test
    public void pauseJob() throws SchedulerException, InterruptedException {
        //暂停任务
        scheduler.pauseJob(JobKey.jobKey("job001","group001"));
        Thread.sleep(60*1000L);
        scheduler.shutdown();
    }
    

(10)恢复所有任务

@Test
public void resumeAll() throws SchedulerException, InterruptedException {
    scheduler.resumeAll();
    Thread.sleep(60*1000L);
}

(11)暂停所有任务

@Test
public void pauseAll() throws SchedulerException, InterruptedException {
    scheduler.pauseAll();
    Thread.sleep(60*1000L);
}

(12)任务信息检出

//GroupMatcher<JobKey>
GroupMatcher<JobKey> matcher=GroupMatcher.anyJobGroup();
//Set<JobKey>
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
for (JobKey jobKey : jobKeys) {
    //List<Trigger>
    List<? extends Trigger> triggers=scheduler.getTriggersOfJob(jobKey);
    for (Trigger trigger : triggers) {
        System.out.println("Job:"+jobKey.getName()+"-- trigger:"+trigger.getStartTime()+"-- group:"+jobKey.getGroup());
    }
}
Thread.sleep(60*1000L);

(13)查询正在运行的任务

  • 方法获取的不是打开状态的任务,而是正在执行的任务

    List<JobExecutionContext> contexts = scheduler.getCurrentlyExecutingJobs();
    System.out.println(contexts.size());
    if (CollectionUtils.isEmpty(contexts)){
        System.out.println("无正在运行的任务");
    }else {
        for (JobExecutionContext context:contexts) {
            //JobDetail
            JobDetail jobDetail = context.getJobDetail();
            //JobKey
            JobKey jobKey = jobDetail.getKey();
            //List<Trigger>
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger: triggers) {
                System.out.println("Job:"+jobKey.getName()+"-- trigger:"+trigger.getStartTime()+"-- group:"+jobKey.getGroup());
            }
        }
    }
    

(14)更新Trigger

    //TriggerKey
    TriggerKey triggerKey = TriggerKey.triggerKey("trigger001", "group002");
    //Trigger
    Trigger trigger = ((CronTrigger)scheduler.getTrigger(triggerKey))
            .getTriggerBuilder()
            .withIdentity(triggerKey)
            .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))
            .build();
    //reschedulerJob
    scheduler.rescheduleJob(triggerKey,trigger);
    scheduler.resumeJob(JobKey.jobKey("job002","group002"));
    Thread.sleep(60*1000L);

 

结束

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值