前段时间,公司要求得用到定时任务的批量操作,所以学习了下quartz任务调度 。
Quartz任务调度框架用法
Quartz是什么?
Quartz 是一个任务日程管理系统,这个系统可以与任何其他软件系统集成或者一起使用。术语“日程进度管理器”可能对于不同的人有不同的理解。当你阅读这个指南之后,你会对这个术语有固定的理解。简而言之,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。为了达到预想目的,或者是能够写出与工程最“自然”衔接的软件代码,Quartz 相地灵活,并且包括了多个用法范例,可以单独运用这些范例或者组合运用这些范例。
Quartz 相当“轻量”,并且需要非常少的步骤/配置,如果需求比较基本,Quartz确实非常容易使用。
Quartz 具有容错性,并且可以在你系统重起的时候持久化(记住)被纳入日程的任务。
虽然 Quartz 对于按照简单地给定日程运行的系统时非常有用,但是,当你学会如何使用它来驱动你应用中的商务过程,那么你才会认识到它的全部潜能。
为什么定时任务不使用java.util.Timer?
从 JDK1.3 开始,Java 有了内建的定时器功能,即,通过 java.util.Timer 和java.util.TimerTask 来实现。但是,使用java提供的定时器的API有如下的不足:
1. Java 定时器没有持久化机制。
2. Java 定时器的日程管理不够灵活(只能设置开始时间、重复的间隔,设置特定的日期、时间等)
3. Java 定时器没有使用线程池(每个 Java 定时器使用一个线程)
4. Java 定时器没有切实的管理方案,你不得不自己完成存储、组织、恢复任务的措施。
入门demo
首先,下载quartz,官方地址 http://www.quartz-scheduler.org/ 。下载好之后,创建一个maven工程 引入官网提供的maven依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
开始编写 入门案例!
package com.quartz.demo1;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class Demo1 {
public static void main(String[] args) throws SchedulerException {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();//创建调度器对象
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();//触发器对象
scheduler.scheduleJob(job, trigger);
scheduler.start();
}
}
package com.quartz.demo1;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloJob implements Job {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void execute(JobExecutionContext context) throws JobExecutionException {
logger.info("hello,quartz!");
}
}
JobDetail 对象由 Quartz 客户端在 Job 被加入到 scheduler 时创建。它包含了 Job的各种设置属性以及一个 JobDataMap 对象,这个对象被用来存储给定 Job 类实例的状态信息。
Trigger 对象被用来触发 jobs 的执行。你希望将任务纳入到进度,要实例化一个Trigger 并且“调整”它的属性以满足你想要的进度安排。Triggers 也有一个 JobDataMap与之关联,这非常有利于向触发器所触发的 Job 传递参数。Quartz 打包了很多不同类型的 Trigger,但最常用的 Trigge 类是 SimpleTrigger 和 CronTrigger。
是不是感觉很简单,就是这么简单!但我们项目中一般是使用quartz跟spring整合的方式完成任务的定时调度,接下来我们来完成与spring整合的demo。
与spring整合
依赖与tomcat插件
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<port>9888</port>
</configuration>
</plugin>
</plugins>
</build>
spring整合quartz的配置文件
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:component-scan base-package="com.job" />
<bean id="helloJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.job.demo.HelloJob"/>
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5"/>
</map>
</property>
</bean>
<!-- ======================== 调度触发器 ======================== -->
<bean id="cronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="helloJob"></property>
<property name="cronExpression" value="0 54 * * * ?"></property><!--cron表达式-->
</bean>
<!-- ======================== 调度工厂 ======================== -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory" />
<property name="triggers">
<list>
<ref bean="cronTriggerBean" />
</list>
</property>
</bean>
</beans>
log4J.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
Web.xml配置spring监听器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- spring配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- spring核心监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
java代码编写
job工厂类
package com.job.demo;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Service;
@Service("jobFactory")
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
执行代码
package com.job.demo;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.service.demo.HelloService;
public class HelloJob extends QuartzJobBean {
@Autowired
private HelloService helloService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
helloService.sayHello();
}
}
Service实现编写
package com.service.demo;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public void sayHello() {
System.out.println("hello,quartz service !");
}
}
大功告成!!完成入门。