今天有一个任务需要定时执行,考虑了几个方法:
(1)python或者shell写一些脚本,然后crontab方法
(2)Spring+JDK Timer
想想上个项目使用的是第二种情况的,实际使用中存在了诸多的问题,比如
在应用过程中十分痛苦,最近重新搜了一下,发现一个更加好用的工具:Quartz ! 这个工具在美团中的有大量使用,详见他们的官方博客: http://tech.meituan.com/mt-crm-quartz.html。
光看博客对它有个了解,但是我们还是从官方文档-2.2版本的html文档( https://quartz-scheduler.org/generated/2.2.2/html/qtz-all/#page/quartz-scheduler-webhelp%2Fto-quartz_scheduler_online_documentation_library.html)来学习这个强大的工具。
首先,对quartz有个大致了解,
Quartz是Java领域最著名的开源任务调度工具。Quartz提供了极为广泛的特性如持久化任务,集群和分布式任务等,其特点如下:
更多详情还是移步官方网站吧( https://quartz-scheduler.org/)
下面我们以实际的例子来学习 在Spring中使用Quartz有两种方式实现:
- 第一种是任务类继承QuartzJobBean;
- 第二种则是在配置文件里定义任务类和要执行的方法,类和方法可以是普通类;
我们分别来看一下这两种方式:
(1)任务类继承QuartzJobBean
首相定义一个job,就是我们要具体跑的任务
package xiaolong.com.quartz.play; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.util.Date; /** * @author zhangxiaolong */ public class SimpleQuartzJob implements Job { // static Log logger = LogFactory.getLog(ScanDirectoryJob.class);//日志记录器 public SimpleQuartzJob() { } @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("In SimpleQuartzJob - executing its JOB at " + new Date() + " by " + context.getTrigger().getDescription()); } }
然后定义定义我们的触发器trigger
package xiaolong.com.quartz.play; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; /** * @author zhangxiaolong */ public class SimpleTriggerRunner { public static void main(String[] args) { SimpleTriggerRunner simpleTriggerRunner = new SimpleTriggerRunner(); try { Scheduler scheduler = simpleTriggerRunner.createScheduler(); simpleTriggerRunner.scheduleJob(scheduler); scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } } public Scheduler createScheduler() throws SchedulerException { // 创建调度器 return StdSchedulerFactory.getDefaultScheduler(); } //Create and Schedule a ScanDirectoryJob with the Scheduler private void scheduleJob(Scheduler scheduler) throws SchedulerException { // Create a JobDetail for the Job JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob","group1").build(); // Date runTime = evenMinuteDate(new Date()); Trigger trigger = newTrigger().withIdentity("myTrigger","group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).withRepeatCount(10)).build(); // Trigger trigger = newTrigger().withIdentity("myTrigger","group1").startAt(RunTime).build(); scheduler.scheduleJob(jobDetail, trigger); } }
最后,我们简单用main方法来调用定时任务;
当然触发器还有一种类似于crontab的方式,即
package xiaolong.com.quartz.play; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; /** * @author zhangxiaolong */ public class CronTriggerRunner { public static void main(String[] args) { CronTriggerRunner cronTriggerRunner = new CronTriggerRunner(); try { cronTriggerRunner.createScheduler(); cronTriggerRunner.scheduleJob2(cronTriggerRunner.getScheduler()); cronTriggerRunner.start(); } catch (SchedulerException e) { e.printStackTrace(); } } private void start() { if (null != scheduler) { try { if (scheduler.isStarted()) { System.out.println("has started!"); } scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } } } private Scheduler scheduler; public void createScheduler() throws SchedulerException { // 创建调度器 scheduler = StdSchedulerFactory.getDefaultScheduler(); } private void scheduleJob(Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob2","group1").build(); CronTrigger trigger = newTrigger().withIdentity("myTrigger2","group1").withSchedule(cronSchedule("0/5 * * * * ?")).build(); scheduler.scheduleJob(jobDetail, trigger); } private void scheduleJob2(Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob2","group1").build(); Trigger trigger = newTrigger().withIdentity("myTrigger3","group1").withSchedule(cronSchedule("0/1 * * * * ?")).build(); scheduler.scheduleJob(jobDetail, trigger); } private void stop() { if (null != scheduler) { try { if (!scheduler.isShutdown()) { scheduler.shutdown(true); } } catch (SchedulerException e) { e.printStackTrace(); } } } public Scheduler getScheduler() { return scheduler; } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } }
(2)在配置文件里定义任务类和要执行的方法,类和方法可以是普通类 在spring的框架中编写一个xml文件, “` xml <?xml version= 1.0
encoding= UTF-8
?>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="autoMatchJobTrigger"/> </list> </property> <property name="autoStartup" value="true"/> </bean> <bean id="autoMatchJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="autoMatchJob"/> <!-- 每隔1小时触发一次 --> <property name="cronExpression" value="0 30 20 ? * *"/> </bean> <bean id="autoMatchJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="autoMatchTask"/> <property name="targetMethod" value="autoMatching"/> <!-- 是否允许任务并发执行。当值为false时,表示必须等到前一个线程处理完毕后才再启一个新的线程 --> <property name="concurrent" value="false"/> </bean> <bean id="autoMatchTask" class="com.baijia.accounting.quartz.AutoMatchingTask"> <property name="start" value="${autoMatchingHolderTask.start:true}"/> </bean>
配置的内容呢,就是按照quartz的流程去配置一下job、trigger、调度器等等,
具体的任务呢,就可以是
public class AutoMatchingTask { private static final Logger logger = LoggerFactory.getLogger(AutoMatchingTask.class); private static ExecutorService es = Executors.newSingleThreadExecutor(); private boolean start; public void setStart(boolean start) { this.start = start; } public void autoMatching() { do something… }
(完)
原创文章,转载请注明:转载自时间记忆
本文链接地址: quartz的简单介绍及应用