Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是彻底由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先肯定(被归入日程)的时间到达时,负责执行(或者通知)其余软件组件的系统。java
Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了全部Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操做,例如:将任务归入日程或者从日程中取消,开始/中止/暂停日程进度。mysql
Quartz 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任务调度的元数据, scheduler 是实际执行调度的控制器。spring
触发器,用于定于任务调度的时间规则,即按照什么时间规则去执行任务。Quartz 中主要提供了四种类型的 trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger。Trigger也有一个相关联的JobDataMap,用于给Job传递一些触发相关的参数。
最经常使用的:
SimpleTrigger:用来触发只需执行一次或者在给定时间触发而且重复N次且每次执行延迟必定时间的任务。
CronTrigger:按照日历触发,例如“每一个周五”,每月10日中午或者10:15分。sql
被调度的任务,主要有两种类型的 job:无状态的(stateless)和有状态的(stateful)。数据库
任务调度器,由 scheduler 工厂建立:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二种工厂 StdSchedulerFactory 使用较多,由于 DirectSchedulerFactory 使用起来不够方便,须要做许多详细的手工编码设置。 Scheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。服务器
做业一旦被调度,调度器须要记住而且跟踪做业和它们的执行次数。Quartz经过一个称之为做业存储(JobStore)的概念来作做业存储和管理。并发
Quartz提供两种基本做业存储类型。第一种类型叫作RAMJobStore,它利用内存来持久化调度程序信息。
优势: 不要外部数据库,配置容易,运行速度快
缺点: 由于调度程序信息是存储在被分配给JVM的内存里面,因此,当应用程序中止运行时,全部调度信息将被丢失。另外由于存储到JVM内存里面,因此能够存储多少个Job和Trigger将会受到限制less
第二种类型的做业存储称为JDBC做业存储,提供两种不一样的实现。两种JDBC做业存储都须要JDBC驱动程序和后台数据库来持久化调度程序信息。这两种类型的不一样在于你是否想要控制数据库事务或者释放控制给应用服务器(这相似于J2EE领域中,容器管理事务CMT和Bean管理事务BMT之间的区别),这两种JDBC做业存储是:
JobStoreTX:当你想要控制事务或工做在非应用服务器环境中时使用;
JobStoreCMT:当你工做在应用服务器环境中和想要容器控制事务时使用。
优势: 支持集群,由于全部的任务信息都会保存到数据库中,能够控制事物,还有就是若是应用服务器关闭或者重启,任务信息都不会丢失,而且能够恢复因服务器关闭或者重启而致使执行失败的任务
缺点: 运行速度的快慢取决与链接数据库的快慢ide
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.3</version> </dependency>
定义jobui
public class MyJob implements Job { private static Logger logger = LoggerFactory.getLogger(MyJob.class); public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { //打印当前的执行时间 例如 2019-11-12 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("如今的时间是:"+ sf.format(date)); //具体的业务逻辑 System.out.println("开始生成任务报表 或 开始发送邮件"); logger.info("开始执行定时任务"); } }
建立trigger,schedule,并启动定时任务
//建立一个jobDetail的实例,将该实例与HelloJob Class绑定 JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("myJob").build(); //建立一个Trigger触发器的实例,定义该job当即执行,而且每2秒执行一次,一直执行 SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build(); //建立schedule实例 StdSchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); scheduler.start(); scheduler.scheduleJob(jobDetail,trigger);
先使用quartz自带的建表语句建立表.
配置quartz.properties,以下:
# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # # 调度器实例的名字,使用默认的DefaultQuartzScheduler就好 org.quartz.scheduler.instanceName: DefaultQuartzScheduler # 调度器实例的ID, 选择AUTO org.quartz.scheduler.instanceId:AUTO org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false # 跳过更新检查 org.quartz.scheduler.skipUpdateCheck:true # 配置线程池 org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 10 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true # # quartz默认的是将job信息存储在内存中,quartz集群必须将job信息持久化到数据库中 org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.misfireThreshold:60000 ############ org.quartz.jobStore.useProperties:true #quartz数据表的前缀,quartz的数据表在 quartz-2.2.3\docs\dbTables 文件夹中, #选择对应的数据库版本,将数据库建立出来 org.quartz.jobStore.tablePrefix:QRTZ_ # 最关键的 是否支持集群 选择true org.quartz.jobStore.isClustered:true org.quartz.jobStore.clusterCheckinInterval:15000 # dataSource #org.quartz.jobStore.dataSource:myDS #org.quartz.dataSource.myDS.connectionProvider.class:com.abc.util.MyPoolingconnectionProvider #org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver #org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8 #org.quartz.dataSource.myDS.user: root #org.quartz.dataSource.myDS.password: root #org.quartz.dataSource.myDS.maxConnections: 10
db.properties:
#quartz配置对应数据库 jdbc.quartz.driver=com.mysql.jdbc.Driver jdbc.quartz.url=jdbc:mysql://127.0.0.1:26500/quartz?useUnicode=true&characterEncoding=utf-8 jdbc.quartz.username=root jdbc.quartz.password=vislecaina
spring-quartz.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd "> <!-- 任务 --> <bean id="jobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.fiberhome.quartz.task.job.MyJob"/> <!-- 执行完成仍保留在数据库中 --> <property name="durability" value="true"/> <!-- 这里设置的jobDataAsMap能够传递一些参数给做业任务 --> <property name="jobDataAsMap"> <map> <entry key="wish" value="hello"/> </map> </property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <!-- 这里的JobDetail指的就是咱们配置的做业任务的bean --> <property name="jobDetail" ref="jobDetailFactoryBeanExample" /> <!-- 延迟5秒开始 --> <property name="startDelay" value="5000"></property> <!-- 每3秒重复一次 --> <property name="repeatInterval" value="60000"></property> </bean> <bean id="startQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false"> <property name="configLocation" value="classpath:quartz.properties" /> <property name="dataSource" ref="quartzDataSource" /> <!-- 若是这个覆盖配置为false,quratz启动之后将以数据库的数据为准,配置文件的修改不起做用。--> <property name="overwriteExistingJobs" value="true" /> <!--指定使用哪些触发器,spring会去调度触发相应的触发器,进而对做业任务进行调度处理--> <property name="triggers"> <list> <ref bean="simpleTrigger"/> </list> </property> <property name="jobFactory"> <bean class="com.fiberhome.quartz.task.jobfactory.JobFactory"/> </property> <property name="startupDelay" value="1"/> </bean> </beans>
Job类:
public class MyJob implements Job { @Autowired private UserService userService; /** * 要实现的任务 * * @param context job上下文 * @throws JobExecutionException */ @Override public void execute(JobExecutionContext context) throws JobExecutionException { User user = userService.getUser(1001); System.out.println("执行定时任务..."); System.out.println(user); } }
JobFactory类:
public class JobFactory extends SpringBeanJobFactory { @Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object jobInstance = super.createJobInstance(bundle); autowireCapableBeanFactory.autowireBean(jobInstance); return jobInstance; } }