quartz定时器,及与spring两种整合方式介绍
前言
最近正好用到定时器,这边顺便把定时器quartz做一个简单的总结。
添加依赖
<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.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.6.RELEASE</version> </dependency>
上代码:
public static void simpleTrigger() { try { //创建工厂,获取调度器scheduler Scheduler scheduler = new StdSchedulerFactory().getScheduler(); //构建jobBuilder JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job", "group").build(); //定义一个trigger SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow(). withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build(); //加入调度 scheduler.scheduleJob(jobDetail, simpleTrigger); //启动 scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } }
自定义一个类实现Job接口,实现它的execute方法
public class MyJob implements Job{ @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("现在时间是"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } }
上面就是一个简单的定时器,每两秒执行一次MyJob中的execute方法
这个例子中包含几个重要的类:
- Scheduler:调度器。所有的调度都是由它控制。
- Trigger: 定义触发的条件。例子中,它的类型是SimpleTrigger,每隔2秒中执行一次
- JobDetail :要执行的任务
trigger
SimpleTrigger:指定从某一个时间开始,以一定的时间间隔(单位是毫秒)执行的任务
CronTrigger:指定从某一个时间开始,以一定的时间间隔执行的任务。 但是不同的是SimpleTrigger指定的时间间隔为毫秒,没办法指定每隔一个月执行一次(每月的时间间隔不是固定值),而CronTrigger支持的间隔单位有秒,分钟,小时,天,月,年,星期。相较于SimpleTrigger有两个优势:1、更方便,比如每隔1小时执行,你不用自己去计算1小时等于多少毫秒。 2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒。
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("triger", "group")
.startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")).build();
这边时间执行参数“*,*,*,*,*,*,*” [秒] [分] [小时] [日] [月] [周] [年] ,具体怎么写不多做阐述,百度上搜索“在线Cron表达式生成器”
整合spring
方式一:JobDetailFactoryBean
1.创建类实现Job接口
public class MyJob implements Job{ @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("现在时间是"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } }
2.xml实现
<bean id="jobFactory" class="com.cao.quartz.MyJobFactory"></bean> <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 指定具体的job类 -->
<property name="jobClass" value="com.cao.quartz.MyJob"></property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail" ></property> <property name="startDelay" value="3000"></property> <property name="repeatInterval" value="2000" ></property> </bean> <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
<property name="jobFactory" ref="jobFactory"></property> <property name="triggers"> <list> <ref bean="simpleTrigger"/> </list> </property>
</bean>
3.解决注入Service为null的问题
定义一个JobFactory
public class JobFactory extends org.springframework.scheduling.quartz.SpringBeanJobFactory{ @Autowired private AutowireCapableBeanFactory beanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object jobInstance = super.createJobInstance(bundle); beanFactory.autowireBean(jobInstance); return jobInstance; } }
接下来把他配置到Spring当中去
<bean id="jobFactory" class="com.cao.quartz.MyJobFactory"></bean>
然后在把org.springframework.scheduling.quartz.SchedulerFactoryBean的jobFactory设置成我们自己的。
<bean name="MyScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 其他属性省略 --> <property name="jobFactory" ref="jobFactory"></property> </bean>
方式二.MethodInvokingJobDetailFactoryBean
1.定义一个方法,这边不需要实现Job接口
public class SpringJob { public void doSomething() { System.out.println("现在时间是"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } }
xml配置:
<!--执行的类 --> <bean id="testJob" class="com.cao.controller.TestQuartz" ></bean> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" > <!--要执行的类 ,将上面的注入 --> <property name="targetObject" ref="testJob" ></property> <!-- 任务要执行的方法 --> <property name="targetMethod" value="doSomething"></property> <!-- 上一次未执行完成的,要等待有再执行。 --> <property name="concurrent" value="false"></property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <!--上面定义的jobDetail --> <property name="jobDetail" ref="jobDetail" ></property> <property name="startDelay" value="3000"></property> <property name="repeatInterval" value="2000" ></property> </bean> <!-- <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail"/> <property name="cronExpression" value="0/2 * * * * ?"/> </bean> --> <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 --> <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" > <property name="triggers"> <list> <ref bean="simpleTrigger"/> <!-- <ref bean="cronTrigger"/> --> </list> </property> </bean>