Spring整合Quartz实现持久化、动态设定时间
一、spring整合
网上一搜有很多整合的方式,这里我采用了其中的一种(暂时还没有对其他的方法研究过)。
对于spring的整合其中的任务,spring提供了几个类、接口(这些类都实现了Job接口):
org.springframework.scheduling.quartz.QuartzJobBean
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.MethodInvokingJob
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.StatefulMethodInvokingJob
QuartzJobBean和MethodInvokingJob是无状态的,StatefulMethodInvokingJob是有状态的。
可以选择自己的需求选择继承与哪个类。
关于Scheduler在Spring上的配置:
<bean name="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="applicationContextSchedulerContextKey" value="applicationContextKey" /> <property name="autoStartup" value="true" /> <property name="configLocation" value="classpath:spring/quartz.properties"/> </bean>
注意:其中lazy-init="false",和 <property name="autoStartup" value="true"/>最好按照自己的需求作统一的配置
二、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 #============================================================================ org.quartz.scheduler.instanceName = DefaultQuartzScheduler org.quartz.scheduler.rmi.export = false org.quartz.scheduler.rmi.proxy = false org.quartz.scheduler.wrapJobExecutionInUserTransaction = false #============================================================================ # Configure ThreadPool #============================================================================ org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.threadPriority = 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true #============================================================================ # Configure JobStore #============================================================================ #org.quartz.scheduler.classLoadHelper.class=org.quartz.simpl.CascadingClassLoadHelper org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.useProperties = true org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate #havent cluster spring #org.quartz.jobStore.dataSource = myDS org.quartz.jobStore.tablePrefix = qrtz_ org.quartz.jobStore.isClustered = false org.quartz.jobStore.maxMisfiresToHandleAtATime=1 #============================================================== #Non-Managed Configure Datasource if you don't use spring cluster #============================================================== #org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver #org.quartz.dataSource.myDS.URL = jdbc\:mysql\://localhost\:3306/qrtz #org.quartz.dataSource.myDS.user = root #org.quartz.dataSource.myDS.password = root #org.quartz.dataSource.myDS.maxConnections =10
这里要备注的是:org.quartz.jobStore.misfireThreshold = 60000
这个属性是配置当发现触发器过时,允许做就之内的trigger任有效。对于详细了解其中的机制,可以查看数据库的变化,特别是数据库中的QRTZ_FIRED_TRIGGERS表。
对于其状态有ACQUIRED和EXECUTING两个状态进行转化,并因此会影响QRTZ_TRIGGERS的表的数据。(个人猜想:quartz是利用这几个字段来保存断点的)
三、下面是项目的搭建代码:
任务类信息类JobModel
public class JobModel { private String jobName; private String group;//对于job,trigger相互绑定的,采用相同的group private Class<?> jobClass; private Trigger trigger; public JobModel() { super(); } //.....getter,setter }
定义一个无状态的Job(若定义一个有状态的Job,需要继承与StatefulMethodInvokingJob)
public class CommonJob extends MethodInvokingJob{ @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("commonJob executing ..."); JobDataMap dataMap = context.getJobDetail().getJobDataMap(); int value = Integer.parseInt(dataMap.getString("key")); System.out.println("value is " + value); dataMap.put("key", new Integer(++value).toString()); } }
SchedulerManager一共对在scheduler中操作job
public class QrtzManager { private static Scheduler scheduler; static { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext-quartz2.xml"); scheduler = (StdScheduler) context.getBean("quartzScheduler"); } public void standBy(){ try { scheduler.standby(); } catch (SchedulerException e) { e.printStackTrace(); } } public void start(){ try { scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } } //add a job public void deploy(JobModel model,JobDataMap dataMap){ JobDetail jobDetail = new JobDetail(model.getJobName(),model.getGroup(),model.getJobClass()); jobDetail.setJobDataMap(dataMap); try { scheduler.scheduleJob(jobDetail,model.getTrigger()); } catch (SchedulerException e) { e.printStackTrace(); } } //delete a job public void unDeploy(String jobName,String group){ if (jobName.equals("") || group.equals("")) { return ; } try { scheduler.deleteJob(jobName, group); } catch (SchedulerException e) { e.printStackTrace(); } } }
测试类
package com.lps.schedulerserver.service02; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.junit.Test; import org.quartz.CronTrigger; import org.quartz.JobDataMap; import org.quartz.SimpleTrigger; import org.quartz.Trigger; public class Main { public static void main(String[] args) { Trigger trigger = new SimpleTrigger("trigger02", "group02", new Date(), parse("2012-12-12 18:30:00"), 5, 10000L); JobModel model1 = new JobModel("job01", "group01", CommonJob.class, trigger); String expression = "0/15 * * ? * *"; Trigger trigger2 = null; try { trigger2 = new CronTrigger("trigger01", "group", expression); trigger2.setStartTime(new Date()); } catch (ParseException e) { e.printStackTrace(); } JobModel model2 = new JobModel("job02","group02",StatefulJob.class,trigger2); QrtzManager manager = new QrtzManager(); //jobdatamap JobDataMap dataMap = new JobDataMap(); dataMap.put("key", "1"); manager.deploy(model2, dataMap); System.out.println("deploy model2 at:"+new Date()); } public static Date parse(String str){ DateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); Date date = null ; try { date = format.parse(str); } catch (ParseException e) { e.printStackTrace(); } return date; } @Test public void deleteJob(){ QrtzManager manager = new QrtzManager(); manager.unDeploy("job01","group01"); } }