Spring-定时任务之Quartz
2016-02-02 21:06
369 查看
最近的项目中,使用了定时任务。网上搜索了很多关于定时任务的解决方案,大概总结一下有以下几种解决思路1)java.util.Timer;2)Quartz;3)Spring3.0以后自带的task。本次项目解决方案采用的是Quartz来实现定时任务。
在 项目的过程中,期初需要的需求很简单(完成定时请求服务端的数据),采用了Quartz的配置方式,简单的配置后即可完成定时的任务,这算是静态定时任务。不久后,需要定时任务由用户自己配置,如配置任务执行周期、任务内容、开启/运行任务、添加/删除任务等,在网上寻找新的解决方法,最终选择采用了quartz的编程实现方式。
下面分别介绍这两种实现不同需求的定时任务的实现过程(原理性以后补充)。
方法一、配置实现
主要步骤:
a)在Spring.xml中,调度器里添加了两个触发器simpleTrigger和cronTrigger,前者是简单定时触发,后者采用了cron表达式。在类loopTask中,实现了两个定时触发器响应方法。
b)MyLookTask类,在该类中配置了服务类AService,可以在定时任务方法中使用(强调这个是因为在第二个动态定时任务中失效。)
方法二、编码实现
编码实现,即在程序中实现动态定时任务,这里主要采用了几个工具类来完成定时任务:
MyJob类:实现了org.quartz.Job接口;
QuartUntils类:调度器工具类;
DutiesAgency类:在项目中,在定时任务调用的方法里无法使用服务类(由注解或配置注入的服务类),所以添加了一个代理任务,该代理任务包含了具体任务和被具体任务调用的服务。
具体实现类如下:
在action里调用任务的添加任务,定时内容由前台配置,服务在action里注入,将定时内容和服务包装在代理里。
以上代码简单实现了动态可配置的定时任务。
本次动态的定时任务,为能够使用originalDataService,经过几番资料查询,请教大神,最终也只是实现了,但直觉上不是最佳的方式。以下几种方式均无法实现originalDataService服务;在execute中使用:至于为什么Spring注解失效,分别做了如下测试。
1)在每次MyJob类中execute方法调用时,其构造函数是执行的;
2)将一个Action类(项目采用了Spring+struts2框架)类实现Job接口,在action的execute定时执行时,该action的注解成员也均为null;
3)项目在加载时,originalDataService、MyJob以及originalDataService类的构造函数是执行的;
4在MyJob.execute的方法里直接实例化服务类,而在服务类中不使用注解/配置方式,能够实现,但和整个项目编码方式迥异,不爽。
部分代码如下:
此外,真诚感谢以下博客提供宝贵的实现代码:
1、Spring定时任务的几种实现
2、Spring定时任务之quartz
3、Quartz2.x增删改查工具类
4、Quartz在Spring中如何动态配置时间
5、Spring3整合Quartz2实现定时任务二:动态添加任务
在 项目的过程中,期初需要的需求很简单(完成定时请求服务端的数据),采用了Quartz的配置方式,简单的配置后即可完成定时的任务,这算是静态定时任务。不久后,需要定时任务由用户自己配置,如配置任务执行周期、任务内容、开启/运行任务、添加/删除任务等,在网上寻找新的解决方法,最终选择采用了quartz的编程实现方式。
下面分别介绍这两种实现不同需求的定时任务的实现过程(原理性以后补充)。
方法一、配置实现
主要步骤:
a)在Spring.xml中,调度器里添加了两个触发器simpleTrigger和cronTrigger,前者是简单定时触发,后者采用了cron表达式。在类loopTask中,实现了两个定时触发器响应方法。
<bean id="loopTask" class="xxxxxx.MyLoopTask"/> <bean id="loopCreateTable" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="loopTask" /> <property name="targetMethod" value="loopCreateDataTable" /> </bean> <bean id="loopCreateTable" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="loopTask" /> <property name="targetMethod" value="loopCreateDataTable" /> </bean> <bean id="loopOriginalData" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="loopTask" /> <property name="targetMethod" value="loopOriginalData" /> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="loopOriginalData" /> <property name="startDelay" value="10000" /> <property name="repeatInterval" value="${httpconn1.period}" /> </bean> <bean id="cronTrigger" class="org.springframework.scheduling.qu 4000 artz.CronTriggerFactoryBean"> <property name="jobDetail" ref="loopCreateTable" /> <property name="cronExpression" value="0 0 * * * ?" /> </bean>
b)MyLookTask类,在该类中配置了服务类AService,可以在定时任务方法中使用(强调这个是因为在第二个动态定时任务中失效。)
public class MyLoopTask { @Resource(name="AService") private AService aservice; public void loopCreateDataTable() { //使用aservice } public void loopOriginalData() { //使用aservice }
方法二、编码实现
编码实现,即在程序中实现动态定时任务,这里主要采用了几个工具类来完成定时任务:
MyJob类:实现了org.quartz.Job接口;
QuartUntils类:调度器工具类;
DutiesAgency类:在项目中,在定时任务调用的方法里无法使用服务类(由注解或配置注入的服务类),所以添加了一个代理任务,该代理任务包含了具体任务和被具体任务调用的服务。
具体实现类如下:
public class QuartzUntils { private Logger log = null; private Scheduler scheduler = null; public static final String DATA_KEY = "STATE_DATA"; public QuartzUntils() { try { log = org.apache.logging.log4j.LogManager.getLogger(); scheduler = new StdSchedulerFactory().getScheduler(); log.info("初始化调度器 "); } catch (SchedulerException ex) { log.error("初始化调度器=> [失败]:" + ex.getLocalizedMessage()); } } public void addJob(DutiesAgency da) { try { //构造任务 JobDetail job = newJob(MyJob.class) .withIdentity(da.getCrontabMangeEntity().getJobName(), da.getCrontabMangeEntity().getJobGroup()) .build(); job.getJobDataMap().put("DutiesAgency",da); //构造任务触发器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(da.getCrontabMangeEntity().getCronExpression()); Trigger trg = newTrigger() .withIdentity(da.getCrontabMangeEntity().getJobName(), da.getCrontabMangeEntity().getJobName()) .withSchedule(scheduleBuilder) .build(); //将作业添加到调度器 scheduler.scheduleJob(job, trg); log.info("创建作业=> [作业名称:" +da.getCrontabMangeEntity().getJobName() + " 作业组:" + da.getCrontabMangeEntity().getJobName() + "] "); } catch (SchedulerException e) { e.printStackTrace(); } } public void removeJob(String name, String group) { try { TriggerKey tk = TriggerKey.triggerKey(name, group); scheduler.pauseTrigger(tk);//停止触发器 scheduler.unscheduleJob(tk);//移除触发器 JobKey jobKey = JobKey.jobKey(name, group); scheduler.deleteJob(jobKey);//删除作业 log.info("删除作业=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("删除作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } public void pauseJob(String name, String group) { try { JobKey jobKey = JobKey.jobKey(name, group); scheduler.pauseJob(jobKey); log.info("暂停作业=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("暂停作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } public void resumeJob(String name, String group) { try { JobKey jobKey = JobKey.jobKey(name, group); scheduler.resumeJob(jobKey); log.info("恢复作业=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("恢复作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } public void modifyTime(String name, String group, String cronExpression) { try { TriggerKey tk = TriggerKey.triggerKey(name, group); //构造任务触发器 Trigger trg = newTrigger() .withIdentity(name, group) .withSchedule(cronSchedule(cronExpression)) .build(); scheduler.rescheduleJob(tk, trg); log.info("修改作业触发时间=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("修改作业触发时间=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } public void start() { try { scheduler.start(); System.out.println("启动调度器"); log.info("启动调度器 "); } catch (SchedulerException e) { e.printStackTrace(); log.error("启动调度器=> [失败]"); } } public void shutdown() { try { scheduler.shutdown(); log.info("停止调度器 "); } catch (SchedulerException e) { e.printStackTrace(); log.error("停止调度器=> [失败]"); } } public static void main(String[] args) { QuartzUntils quartzUntils=new QuartzUntils(); ScheduleJob job = new ScheduleJob(); job.setJobId("10001"); job.setJobName("data_import"); job.setJobGroup("dataWork"); job.setCronExpression("0/5 * * * * ?"); quartzUntils.addJob(job); quartzUntils.start();*/ }
public class MyJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("定时任务开始..."); DutiesAgency da = (DutiesAgency) context.getMergedJobDataMap().get("DutiesAgency"); da.getOriginalDataService().dataDistribution(da.getCrontabMangeEntity()); } }
public class DutiesAgency { private CrontabMangeEntity crontabMangeEntity; private OriginalDataService originalDataService; public CrontabMangeEntity getCrontabMangeEntity() { return crontabMangeEntity; } private void setCrontabMangeEntity(CrontabMangeEntity crontabMangeEntity) { this.crontabMangeEntity = crontabMangeEntity; } public OriginalDataService getOriginalDataService() { return originalDataService; } private void setOriginalDataService(OriginalDataService originalDataService) { this.originalDataService = originalDataService; } public DutiesAgency(CrontabMangeEntity crontabMangeEntity,OriginalDataService originalDataService){ this.crontabMangeEntity=crontabMangeEntity; this.originalDataService=originalDataService; } }
在action里调用任务的添加任务,定时内容由前台配置,服务在action里注入,将定时内容和服务包装在代理里。
quartzUntils.addJob(new DutiesAgency(crontabMangeEntity,originalDataService));
以上代码简单实现了动态可配置的定时任务。
本次动态的定时任务,为能够使用originalDataService,经过几番资料查询,请教大神,最终也只是实现了,但直觉上不是最佳的方式。以下几种方式均无法实现originalDataService服务;在execute中使用:至于为什么Spring注解失效,分别做了如下测试。
1)在每次MyJob类中execute方法调用时,其构造函数是执行的;
2)将一个Action类(项目采用了Spring+struts2框架)类实现Job接口,在action的execute定时执行时,该action的注解成员也均为null;
3)项目在加载时,originalDataService、MyJob以及originalDataService类的构造函数是执行的;
4在MyJob.execute的方法里直接实例化服务类,而在服务类中不使用注解/配置方式,能够实现,但和整个项目编码方式迥异,不爽。
部分代码如下:
@Resource(name="OriginalDataService") private OriginalDataService originalDataService;//尝试1)采用注解,execute里调用为null OriginalDataService originalDataService=new OriginalDataService();//尝试2)错 OriginalDataService originalDataService=new OriginalDataServiceImpl();//尝试3,可以实例化OriginalDataServiceImpl,但OriginalDataServiceImpl类中的注解成员为null,不行。时间匆忙,有时间再研究学习关于定时任务,充实本帖,待续...
此外,真诚感谢以下博客提供宝贵的实现代码:
1、Spring定时任务的几种实现
2、Spring定时任务之quartz
3、Quartz2.x增删改查工具类
4、Quartz在Spring中如何动态配置时间
5、Spring3整合Quartz2实现定时任务二:动态添加任务
相关文章推荐
- Maven学习 (三) 使用m2eclipse创建web项目
- java.io.Serializable
- 应用springMVC时如果配置URL映射时如下配置
- Java基础(十)——类加载机制
- Thinking in Java---再谈线程通信
- STRUTS2核心控制器:FilterDispatcher
- java中重载和重写的区别是什么?
- spring依赖注入
- java 单链表实现栈
- Java设计模式(十五)----观察者模式
- JavaBean的命名规则
- spring生成EntityManagerFactory的三种方式
- Spring支持5种类型的增强
- java标识接口
- spring注解事务管理
- Spring切入点表达式常用写法
- struts2拦截器
- struts2上传文件
- spring事务管理
- java Annotation好文章