`

quartz 在spring框架中的使用

 
阅读更多
Quartz

源文: http://www.blogjava.net/baoyaer/articles/155645.html

了解Quartz体系结构

Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,
并在org.quartz通过接口和类对重要的这些核心概念进行描述


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

JobDetail:Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,
以便运行时通过newInstance()的反射机制实例化Job。
因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。
通过该类的构造函数可以更具体地了解它的功用:
JobDetail(java.lang.String name, java.lang.String group, java.lang.Class jobClass),
该构造函数要求指定Job的实现类,以及任务在Scheduler中的组名和Job名称;

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关联,以便排除或包含某些时间点。

假设,我们安排每周星期一早上10:00执行任务,但是如果碰到法定的节日,任务则不执行,
这时就需要在Trigger触发机制的基础上使用Calendar进行定点排除。针对不同时间段类型,
Quartz在org.quartz.impl.calendar包下提供了若干个Calendar的实现类,
如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义


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

Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
可以通过SchedulerFactory创建一个Scheduler实例。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,
Job和Trigger都可以访问SchedulerContext内的信息。SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,
SchedulerContext为保存和获取数据提供了多个put()和getXxx()的方法。可以通过Scheduler# getContext()获取对应的SchedulerContext实例;

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

SimpleTrigger拥有多个重载的构造函数,用以在不同场合下构造出对应的实例:

●SimpleTrigger(String name, String group):通过该构造函数指定Trigger所属组和名称;

●SimpleTrigger(String name, String group, Date startTime):除指定Trigger所属组和名称外,还可以指定触发的开发时间;

●SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount, long repeatInterval):
除指定以上信息外,还可以指定结束时间、重复执行次数、时间间隔等参数;

●SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval):
这是最复杂的一个构造函数,在指定触发参数的同时,还通过jobGroup和jobName,让该Trigger和Scheduler中的某个任务关联起来。

import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SimpleJob  implements Job{
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println(arg0.getTrigger().getName()+ " triggered. time is:" + (new Date()));		
	}
}


import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;

public class SimpleTriggerRunner {
	public static void main(String[] args) {
		// 创建一个JobDetail实例,指定SimpleJob
		JobDetail jobDetail = new JobDetail("job1_1", "jGroup1",
				SimpleJob.class);
		// 通过SimpleTrigger定义调度规则:马上启动,每2秒运行一次,共运行100次
		SimpleTrigger simpleTrigger = new SimpleTrigger("trigger1_1", "tgroup1");
		simpleTrigger.setStartTime(new Date());
		simpleTrigger.setRepeatInterval(2000);
		simpleTrigger.setRepeatCount(100);
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory schedulerFactory = new StdSchedulerFactory();
		Scheduler scheduler;
		try {
			scheduler = schedulerFactory.getScheduler();
			scheduler.scheduleJob(jobDetail, simpleTrigger);// 注册并进行调度
			scheduler.start();// 调度启动
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


CronTrigger 能够提供比 SimpleTrigger 更有具体实际意义的调度方案,调度规则基于 Cron 表达式,CronTrigger 支持日历相关的重复时间间隔(比如每月第一个周一执行),
而不是简单的周期时间间隔。因此,相对于SimpleTrigger而言,CronTrigger在使用上也要复杂一些。

import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class CronTriggerRunner {
	public static void main(String args[]) {
		try {
			JobDetail jobDetail = new JobDetail("job1_2", "jGroup1",
					SimpleJob.class);
			// 1:创建CronTrigger,指定组及名称
			CronTrigger cronTrigger = new CronTrigger("trigger1_2", "tgroup1");
			CronExpression cexp = new CronExpression("0/5 * * * * ?");// -2:定义Cron表达式
			cronTrigger.setCronExpression(cexp);// -3:设置Cron表达式
			SchedulerFactory schedulerFactory = new StdSchedulerFactory();
			Scheduler scheduler = schedulerFactory.getScheduler();
			scheduler.scheduleJob(jobDetail, cronTrigger);
			scheduler.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

任务调度信息存储

在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。
不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。



通过配置文件调整任务调度信息的保存策略

其实Quartz JAR文件的org.quartz包下就包含了一个quartz.properties属性配置文件并提供了默认设置。如果需要调整默认配置,
可以在类路径下建立一个新的quartz.properties,它将自动被Quartz加载并覆盖默认的设置。

先来了解一下Quartz的默认属性配置文件:

配置详细介绍:http://www.quartz-scheduler.org/documentation/quartz-1.x/configuration/ConfigMain

代码清单5 quartz.properties:默认配置

①集群的配置,这里不使用集群
#instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同 
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
#属性为 AUTO即可,程序会基于主机名和时间戳来产生实例 ID
org.quartz.scheduler.instanceId = AUTO
#通过rmi作为服务器导出Quartz Scheduler
org.quartz.scheduler.rmi.export = false
#是否支持连接远程服务器的scheduler
org.quartz.scheduler.rmi.proxy = false
#在调用job之前,是否开启一个用户事务
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

②配置调度器的线程池

#线程池实现类,采用SimpleThreadPool即可
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#控制多少个线程被创建用来调度Job
org.quartz.threadPool.threadCount = 10
#设置工作者线程的优先级
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

③配置任务调度现场数据保存机制

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = true
#org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 30000
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
#org.quartz.jobStore.doubleCheckLockMisfireHandler=fal

Quartz的属性配置文件主要包括三方面的信息:

1)集群信息;
2)调度器线程池;
3)任务调度现场数据的保存。

如果任务数目很大时,可以通过增大线程池的大小得到更好的性能。默认情况下,Quartz采用org.quartz.simpl.RAMJobStore保存任务的现场数据,
顾名思义,信息保存在RAM内存中,我们可以通过以下设置将任务调度现场数据保存到数据库中

Spring配置

<?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:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" default-autowire="byName">

	<bean id="scheduleService" class="com.erayt.frame.batch.ScheduleService">
		<property name="scheduler" ref="scheduler" />
		<property name="tgrGroup" value="${GROUP_TGR}" />
		<property name="tgrBatchtoday" value="${BATCHTODAYTGR_NAME}" />
	</bean>

    <bean id="scheduler"
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<!-- 指定数据源 -->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="schedulerName" value="XREPORT-PFUND-SCHEDULER" />
		<property name="configLocation"
			value="classpath:quartz.properties" />
		<!--是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,
		可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文 -->
		<property name="applicationContextSchedulerContextKey"
			value="applicationContextKey" />
		<property name="autoStartup" value="true" />
		<property name="startupDelay" value="10" />
		<property name="overwriteExistingJobs" value="true" />
		<property name="triggers">
			<list>
			    <ref local="batchTrigger"/>
			</list>
		</property>
		<property name="jobDetails">
			<list>
				<ref local="pfundzJob" />
			</list>
		</property>
		<property name="schedulerContextAsMap">
		    <map>
                <entry key="tgrGroup" value="${GROUP_TGR}"/>
            </map>
		</property>
	</bean>
	
	<bean id="batchTrigger" class="org.quartz.CronTrigger">
		<property name="name" value="${BATCHTODAYTGR_NAME}" />
		<property name="group" value="基金任务组" />
		<property name="jobGroup" value="${GROUP_JOB}" />
    		<property name="jobName" value="pfundzJob" /><!-- 需要找到与之对应的配置 -->
		<property name="cronExpression" value="${BATCHTODAY_TIME}" />
	</bean>		
	
    <bean id="pfundzJob"
    	class="org.springframework.scheduling.quartz.JobDetailBean">
    	<property name="jobClass" value="com.erayt.pfund.batch.PfundzJob" />
    	<property name="group" value="${GROUP_JOB}" />
    	<!-- 标识job是持久的,删除触发器的时候不被删除 -->
    	<property name="durability" value="true" />
    	<!--requestsRecovery属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务-->
    	<property name="requestsRecovery" value="false" />
    </bean>
	
	<bean id="pfundzOverNightBatch" class="com.erayt.pfund.batch.PfundzOverNightBatch">
		<property name="batchList">
			<list>
				<!-- <ref bean="exportDBHandler"/> -->
				<ref bean="scheduleJobHandler"/>
				<ref bean="changeSystemDate"/>
				<ref bean="synchronizeCache"/>
			</list>
		</property>
	</bean>		
</beans>


取得Spring的调度bean并执行


public class PfundzJob extends QuartzJobBean {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(PfundzJob.class);
	private static final String APPLICATION_CONTEXT_SCHEDULER_CONTEXTKEY = "applicationContextKey";
	/**
	 * 晚批处理
	 */
	public static final int TYPE_OVERNIGHT = 1;
	
	protected void executeInternal(JobExecutionContext arg0)
			throws JobExecutionException {
		try {
			XmlWebApplicationContext context = (XmlWebApplicationContext) arg0
					.getScheduler().getContext()
					.get(APPLICATION_CONTEXT_SCHEDULER_CONTEXTKEY);
			PfundzOverNightBatch overNightBatch = (PfundzOverNightBatch) context.getBean("pfundzOverNightBatch");
			overNightBatch.exector();
		} catch (SchedulerException e) {
			LOGGER.error("晚间批量任务调度失败!【触发器名称:"+arg0.getTrigger().getName()+"】");
		}
	}
}

 

分享到:
评论

相关推荐

    quartz整合springbatch动态集群定时实现mysql参考

    通过这个项目,开发者可以学习到如何在分布式环境中使用Quartz进行定时任务调度,以及如何利用Spring Batch进行批量数据处理。同时,了解如何将这些组件与MySQL数据库相结合,实现高可用性和可扩展性。对于希望构建...

    spring quartz 时间调用框架

    Spring Quartz是一个在Spring框架中集成的时间调度插件,它允许开发者方便地创建和管理定时任务。Quartz是Java领域的一款功能强大的作业调度库,而Spring通过其优秀的IoC(Inversion of Control,控制反转)和AOP...

    quartz和spring-quartz

    而Spring-Quartz则是Spring框架对Quartz的集成,它使得在Spring应用中使用Quartz变得更加方便。 Quartz的核心概念包括Job(作业)、Trigger(触发器)和Calendar(日历)。Job是实际要执行的任务,Trigger定义了Job...

    quartz 在spring中使用服务定时执行的例子

    在Spring框架中集成Quartz,可以方便地实现复杂的工作调度需求。本文将详细介绍如何在Spring项目中配置并使用Quartz服务来定时执行任务。 首先,集成Quartz到Spring项目中,我们需要在项目的`pom.xml`或`build....

    Quartz+Spring定时触发器例子

    而Spring框架则提供了丰富的依赖注入和管理功能,使得集成Quartz变得更加简单。 Quartz的核心概念包括作业(Job)、触发器(Trigger)和调度器(Scheduler)。作业是需要执行的任务,触发器定义了任务何时执行,...

    Spring整合任务调度框架Quartz

    在 Java 领域中,Quartz 是一个非常流行的任务调度框架,而 Spring 是一个非常流行的 Java 框架。在本文中,我们将详细介绍如何将 Spring 整合任务调度框架 Quartz,从而实现任务调度的自动化。 一、使用配置文件...

    SpringQuartz的使用文档

    Spring对Quartz进行了集成,使其更易于在Spring应用程序中使用。Spring提供了`FactoryBean`类,如`SchedulerFactoryBean`,用于创建和管理Quartz的`Scheduler`实例。这使得我们可以利用Spring的依赖注入(DI)和管理...

    Quartz+spring定时任务demo

    Quartz 是一个开源的作业调度框架,用于在 Java 应用程序中实现复杂的时间调度任务。它允许开发者定义定时任务并将...通过学习这个 demo,开发者可以掌握在企业级应用中使用 Quartz 和 Spring 进行定时任务调度的方法。

    spring2与quartz在Web整合

    Spring 2 和 Quartz 是两个在 Java Web 开发中非常重要的框架。Spring 是一个全面的开源应用框架,提供了依赖注入(DI)、面向切面编程(AOP)以及丰富的数据访问和事务管理功能。Quartz,则是一个功能强大的作业...

    quartz在spring中的使用实例

    在Spring框架中整合Quartz,可以方便地管理并执行定时任务,提高系统的可扩展性和灵活性。 首先,我们要了解如何在Spring中集成Quartz。这通常涉及以下几个步骤: 1. **引入依赖**:在项目中,你需要添加Quartz和...

    quartz2.2.1 spring3.1.1

    Quartz 2.2.1 和 Spring 3.1.1 是两个在企业级Java应用开发中常用的开源框架。Quartz 是一个强大的、完全可定制的作业调度库,而 Spring 则是Java应用程序的全面框架,它提供了依赖注入、AOP(面向切面编程)、事务...

    Spring中的Quartz配置-Spring-定时器-java定时器.doc

    在 Spring 框架中,Quartz 是一个非常流行的开源作业调度器,可以实现任务的定时执行。在本篇文章中,我们将讨论如何在 Spring 中配置 Quartz,以实现 Java 定时器的功能。 Quartz 介绍 Quartz 是一个开源的作业...

    Quartz与Spring整合练习源代码

    在Spring中,我们可以使用Spring的`@Component`注解标记Job类,并通过`@Autowired`注入需要的服务,实现任务的业务逻辑。 整合Quartz与Spring的关键在于配置。首先,在Spring的配置文件中,我们需要定义一个`...

    spring的quartz使用实例

    Quartz可以在Java应用中作为独立的服务运行,也可以与Spring框架无缝集成。 2. **Spring整合Quartz的优势** - 简化配置:Spring通过`org.springframework.scheduling.quartz`包提供了对Quartz的封装,使得配置和...

    quartz与spring

    5. 将Job和Trigger关联:在Spring配置中,使用`org.springframework.scheduling.quartz.JobDetailFactoryBean`和`org.springframework.scheduling.quartz.CronTriggerFactoryBean`来创建Job和Trigger,并将它们关联...

    Quartz在Spring中动态设置cronExpression

    给定的部分内容展示了如何在Spring中使用XML配置来定义和管理Quartz的作业和触发器。以下是一些关键的配置元素: - **`schedulerJobDetail`**:这是对JobDetail的配置,指定了目标对象(`targetObject`)和目标方法...

    spring之定时任务实现(spring-task和quartz等不同方式)

    Spring框架提供了一系列工具来支持定时任务的实现,其中包括Spring自带的`spring-task`模块和第三方的Quartz库。下面我们将详细探讨这两种方式以及如何通过注解和非注解的方式进行配置。 首先,`spring-task`是...

    Spring Quartz如何动态配置时间

    在本文中,我们将讨论如何使用 Spring Quartz 实现动态配置时间,并提供了详细的实现步骤和实践经验。 动态配置时间的目的 在实际应用中,任务的执行时间往往需要根据业务需求进行动态调整,以满足不同的需求场景...

    spring-boot使用quartz框架定时发送邮件

    至此,我们就完成了在Spring Boot中使用Quartz框架定时发送邮件并生成报表的任务。这个过程中,我们利用Quartz的Cron表达式来定义任务的执行时间,通过Spring的邮件服务发送邮件,以及通过自定义的业务服务(如`...

    quartz整合springbatch定时集群实现mysql参考模版

    Quartz和SpringBatch是两种在Java开发中广泛使用的框架,Quartz用于任务调度,而SpringBatch则用于批量处理。在大型分布式系统中,结合这两者可以实现强大的定时任务集群功能,尤其是在需要对大量数据进行定时处理的...

Global site tag (gtag.js) - Google Analytics