spring学习笔记(26)spring整合Quartz2持久化稳健任务调度
2016-03-28 17:04
686 查看
在《Quartz任务调度(3)存储与持久化操作配置详细解析 》一文中,我们通过配置quartz.properties属性文件实现了Quartz的数据库持久化操作。现在整合spring的原理,就是相当于把我们在属性文件中的配置属性整合进SchedulerFactoryBean中,来生成我们的Scheduler类。
这里需要特别注意的是,我们通过Bean配置生成的JobDetail和CronTrigger或SimpleTrigger不能被序列化,因而不能持久化到数据库中,如果想要使用持久化任务调度,我们需要编程式创建Quartz的Job等相关实现类。下面是我们的配置实例:
在连接数据前,我们需要先在数据库中创建好对应的表格,在我开始提到的文章内有相关的sql语句。此外,关于quartzProperties还有很多配置属性,如配置线程池、集群等,在我开头提到的那篇文章内都有详细说明。
在这里,如果我们测试时在运行中断后再重复运行,会出现ObjectAlreadyExistsException异常,原因是我们创建的JobDetail和Trigger等的名字和数据库中已有记录冲突,新的任务尝试持久到数据库失败。在程序中,我的处理方法是先捕捉异常,然后调用恢复任务方法,来重新执行异常中断的任务。
这里需要特别注意的是,我们通过Bean配置生成的JobDetail和CronTrigger或SimpleTrigger不能被序列化,因而不能持久化到数据库中,如果想要使用持久化任务调度,我们需要编程式创建Quartz的Job等相关实现类。下面是我们的配置实例:
spring容器配置
<bean id="quartzDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/quartz"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- quartz持久化存储 --> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource"> <ref bean="quartzDataSource" /> </property> <property name="applicationContextSchedulerContextKey" value="applicationContext" /> <property name="quartzProperties"> <props> <!-- JobStore 配置 --> <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop> <!-- 数据表设置 --> <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop> <prop key="org.quartz.jobStore.dataSource">myDatadource</prop> </props> </property> </bean>
在连接数据前,我们需要先在数据库中创建好对应的表格,在我开始提到的文章内有相关的sql语句。此外,关于quartzProperties还有很多配置属性,如配置线程池、集群等,在我开头提到的那篇文章内都有详细说明。
测试类配置
package tool.job; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.quartz.ObjectAlreadyExistsException; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.quartz.impl.StdSchedulerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class pickNewsJob implements Job { @Override public void execute(JobExecutionContext jec) throws JobExecutionException { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); System.out.println("在" + sdf.format(new Date()) + "更新日志"); } public static void main(String args[]) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(pickNewsJob.class) .withIdentity("job1", "jgroup1").build(); SimpleTrigger simpleTrigger = TriggerBuilder .newTrigger() .withIdentity("trigger1") .withSchedule( SimpleScheduleBuilder .repeatSecondlyForTotalCount(10, 2)).startNow() .build(); try{ ApplicationContext ac = new ClassPathXmlApplicationContext("spring/spring-task.xml"); Scheduler scheduler = (Scheduler) ac.getBean("quartzScheduler"); scheduler.scheduleJob(jobDetail, simpleTrigger); scheduler.start(); }catch ( ObjectAlreadyExistsException e) { resumeJob(); } } /** *根据数据库中的记录 恢复异常中断的任务 */ public static void resumeJob() throws SchedulerException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); // ①获取调度器中所有的触发器组 List<String> triggerGroups = scheduler.getTriggerGroupNames(); // ②重新恢复在tgroup1组中,名为trigger1触发器的运行 for (int i = 0; i < triggerGroups.size(); i++) { List<String> triggers = scheduler.getTriggerGroupNames(); for (int j = 0; j < triggers.size(); j++) { Trigger tg = scheduler.getTrigger(new TriggerKey(triggers .get(j), triggerGroups.get(i))); // ②-1:根据名称判断 if (tg instanceof SimpleTrigger && tg.getDescription().equals("jgroup1.DEFAULT")) {//由于我们之前测试没有设置触发器所在组,所以默认为DEFAULT // ②-1:恢复运行 scheduler.resumeJob(new JobKey(triggers.get(j), triggerGroups.get(i))); } } } scheduler.start(); } }
在这里,如果我们测试时在运行中断后再重复运行,会出现ObjectAlreadyExistsException异常,原因是我们创建的JobDetail和Trigger等的名字和数据库中已有记录冲突,新的任务尝试持久到数据库失败。在程序中,我的处理方法是先捕捉异常,然后调用恢复任务方法,来重新执行异常中断的任务。
源码下载
本例源码可到我的github仓库https://github.com/jeanhao/spring的springQuartz文件夹下载相关文章推荐
- JavaWeb基础---Cookie和Session
- atitit.eclipse 新特性总结3.1--4.3
- 工厂模式
- Java实现代理模式(动态代理)
- Java第三次作业
- MyEclipse中使用Maven构建Web开发项目
- JAVA-1-学习历程1:基础知识1
- Java注解
- Spring 3.x jar 包详解 与 依赖关系(转)
- Spring第十篇—举例实现AOP
- Spring第十一篇——–Spring整合Hibernate之配置数据源
- SpringMVC集成Bean Validation 1.1
- Spring第12篇—— Spring对Hibernate的SessionFactory的集成功能
- 事务中的tx:method
- spring学习笔记(25)spring整合quartz多版本实现企业级任务调度
- Spring第13篇—–Spring整合Hibernate之声明式事务管理
- 开发环境配置-eclipse统一格式-1
- spring中使用Quartz任务调度框架
- Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^)
- Java 线程内 递归 Bug 一例