Spring结合Quartz实现多任务定时调用
- 格式:pdf
- 大小:64.71 KB
- 文档页数:9
使用Spring Quartz执行定时任务Quartz是OpenSymphony下的一个开源项目,提供了比JDK的TimeTask更强大的定时任务执行功能。
Spring在Quartz的基础上包装了一层,使得在不使用数据库配置Quartz的情况下,不必再用Quartz的JavaBean设置参数,代码更优雅,可配置性高。
下面我就举个简单的例子。
首先,配置Spring的配置文件,起名叫applicationContext.xml然后编写具体操作代码最后编写运行程序编译后运行RandomPrice就OK了。
需要注意的是,必须使用main函数才能运行,不能使用JUnit。
附:cronExpression配置说明字段允许值允许的特殊字符秒0-59 , - * /分0-59 , - * /小时0-23 , - * /日期1-31 , - * ? / L W C月份1-12 或者 JAN-DEC , - * /星期1-7 或者 SUN-SAT , - * ? / L C #年(可选)留空, 1970-2099 , - * /表达式意义"0 0 12 * * ?" 每天中午12点触发"0 15 10 ? * *" 每天上午10:15触发"0 15 10 * * ?" 每天上午10:15触发"0 15 10 * * ? *" 每天上午10:15触发"0 15 10 * * ? 2005" 2005年的每天上午10:15触发"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发"0 15 10 15 * ?" 每月15日上午10:15触发"0 15 10 L * ?" 每月最后一日的上午10:15触发"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发posted on 2006-04-27 15:53 冰雨阅读(62) 评论(0)编辑收藏引用所属分类: Spring。
Spring+Quartz定时器例子如下:1. javabean类在Test.QuartzJob中1.package Test;2.3.public class QuartzJob {4.public void work()5. {6. System.out.println("Quartz的任务调度!!!");7. }8. }1.<?xml version="1.0"encoding="UTF-8"?>2.<beans xmlns="/schema/beans"3.xmlns:xsi="/2001/XMLSchema-instance"4.xmlns:jee="/schema/jee"5.xsi:schemaLocation="/schema/beans http://w/schema/beans/spring-beans-2.0.xsd6./schema/jee /schema/jee/spring-jee-2.0.xsd">7.8.<!-- 要调用的工作类 -->9.<bean id="quartzJob"class="org.huajun.utils.QuartzJob"></bean>10.<!-- 定义调用对象和调用对象的方法 -->11.<bean id="jobtask"12.class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">13.<!-- 调用的类 -->14.<property name="targetObject">15.<ref bean="quartzJob"/>16.</property>17.<!-- 调用类中的方法 -->18.<property name="targetMethod">19.<value>work</value>20.</property>21.</bean>22.<!-- 定义触发时间 -->23.<bean id="doTime"24.class="org.springframework.scheduling.quartz.CronTriggerBean">25.<property name="jobDetail">26.<ref bean="jobtask"/>27.</property>28.<!-- cron表达式 -->29.<property name="cronExpression">30.<!-- 第 10、30 、50 分钟各执行一次-->31.<value>0 10/20 * * * ?</value>32.</property>33.</bean>34.<!-- 总管理类如果将lazy-init='false'那么容器启动就会执行调度程序 -->35.<bean id="startQuertz"lazy-init="false"autowire="no"36.class="org.springframework.scheduling.quartz.SchedulerFactoryBean">37.<property name="triggers">38.<list>39.<ref bean="doTime"/>40.</list>41.</property>42.</bean>43.44.</beans>3. 设置web.xml对Spring加载1.<?xml version="1.0"encoding="UTF-8"?>2.<web-app version="2.5"xmlns="/xml/ns/javaee"3.xmlns:xsi="/2001/XMLSchema-instance"4.xsi:schemaLocation="/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">5.6.<!-- 加载spring -->7.<context-param>8.<param-name>contextConfigLocation</param-name>9.<param-value>10. /WEB-INF/classes/applicationContext*.xml11.</param-value>12.</context-param>13.<servlet>14.<servlet-name>context</servlet-name>15.<servlet-class>16. org.springframework.web.context.ContextLoaderServlet17.</servlet-class>18.<load-on-startup>1</load-on-startup>19.</servlet>20.21.<welcome-file-list>22.<welcome-file>index.html</welcome-file>23.</welcome-file-list>24.</web-app>注意:1.导入quartz-all-1.5.2.jar 下载2.导入spring.jar(我用的是spring2.0以前的版本)下载如果不导入的话org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBeanorg.springframework.scheduling.quartz.CronTriggerBeanorg.springframework.scheduling.quartz.SchedulerFactoryBeanspring中的这三个类找不到,spring不能正常加载,由于第一次使用Quartz,我就是当时忽略了这一点,浪费了很多时间来调配置,其实配置一点没有错误。
springboot整合quartz定时器实现定时任务详解quartz和TimerTask的区别:timer是jdk⾃带的(可想⽽知,肯定是不怎么好⽤)。
Quartz可以通过cron表达式精确到特定时间执⾏,⽽TimerTask不能。
Quartz拥有TimerTask所有的功能,⽽TimerTask则没有。
学习quartz需要知道的⼏个概念下⾯的概念来⾃⽹上,有点长,没关系,不愿意看可以跳过,下⾯有我个⼈理解精简版Job:是⼀个接⼝,只有⼀个⽅法void execute(JobExecutionContext context),开发者实现该接⼝定义运⾏任务,JobExecutionContext类提供了调度上下⽂的各种信息。
Job运⾏时的信息保存在JobDataMap实例中;JobDetail:Quartz在每次执⾏Job时,都重新创建⼀个Job实例,所以它不直接接受⼀个Job的实例,相反它接收⼀个Job实现类,以便运⾏时通过newInstance()的反射机制实例化Job。
因此需要通过⼀个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这⼀⾓⾊。
Trigger:是⼀个类,描述触发Job执⾏的时间触发规则。
主要有SimpleTrigger和CronTrigger这两个⼦类。
当仅需触发⼀次或者以固定时间间隔周期执⾏,SimpleTrigger是最适合的选择;⽽CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度⽅案:如每早晨9:00执⾏,周⼀、周三、周五下午5:00执⾏等;Calendar:org.quartz.Calendar和java.util.Calendar不同,它是⼀些⽇历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表⼀个⽇历时间点,⽆特殊说明后⾯的Calendar即指org.quartz.Calendar)。
Spring+Quartz实现定时任务的配置方法第一步:.导入相关的jar包(1)spring.jar(2)quartz-1.6.0.jar(3)相关包commons-collections-3.2.jar ; commons-logging-1.1.1.jar; log4j-1.2.16.jar第二步:创建一个类来定义工作定义Quartz工作的第一步是创建一个类来定义工作。
要做到这一点,你需要从Spring 的QuartzJobBean中派生子类。
第三步:配置JobDetail值得注意的是,在这里你并没有直接声明一个TopTenTask Bean,而是声明了一个JobDetailBean。
这是使用Quartz时的一个特点。
JobDetailBean是Quartz的org.quartz.JobDetail的子类,它要求通过jobClass属性来设置一个Job对象。
使用Quartz的JobDetail中的另一个特别之处是TopTenTask的timeout属性是间接设置的。
JobDetail的jobDataAsMap属性接受一个java.util.Map,其中包含了需要设置给jobClass的各种属性。
在这里,这个map包含了一个键值为timeout。
当JobDetailBean实例化时,它会将5注入到EmailReportJob的timeout属性中。
第四步:配置Trigger工作已经被定义好了,接下来你需要调度这个工作。
Quartz的org.quartz.Trigger类描述了何时及以怎样的频度运行一个Quartz工作。
Spring提供了两个触发器,SimpleTriggerBean和CronTriggerBean。
SimpleTriggerBean与ScheduledTimerTask类似。
你可以用它来指定一个工作应该以怎样的频度运行,以及(可选地)在第一次运行工作之前应该等待多久。
例如,要调度报表工作每24小时运行一次,第一次在1小时之后开始运行,可以按照以下方式进行声明:<bean id="topTenTrigger"class="org.springframework.scheduling.quartz.SimpleTriggerBean"><property name="jobDetail"><ref bean="topTenTask"/></property><property name="startDelay"><value>3600000</value></property><property name="repeatInterval"><value>86400000</value></property></bean>属性jobDetail装配了将要被调度的工作,在这个例子中是topTenTask Bean。
现在想要获得在特定时间或者指定时间执行相应功能有两种做法在applicationContext.xml中写入如下Bean<bean id="repeatingTrigger"class="org.springframework.scheduling.timer.ScheduledTimerTask"> <!--启动一秒后执行 --><property name="delay"><value>1000</value></property><!--每隔一小时执行一次 --><property name="period"><value>3600000</value></property><!--注入要监控的javaBean --><property name="timerTask"><ref bean="task" /></property><!--类型是否为fixedRate型,默认为fixedDelay--><property name="fixedRate"><value>true</value></property></bean><bean id="scheduler"class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"><list><ref bean="repeatingTrigger" /></list></property></bean><bean id="task" class="com.css.wam.portlet.SampleTask"><property name="workService"><ref bean="workService" /></property><property name="work"><ref bean="work" /></property></bean>然后写SampleTask类,如下:package com.css.wam.portlet;import java.util.ArrayList;import java.util.Calendar;import java.util.Iterator;import java.util.List;import java.util.TimerTask;import javax.servlet.ServletContext; 字串2import org.apache.jetspeed.security.SecurityException; 字串9 import com.css.wam.service.WorkService; 字串1@SuppressWarnings("unused")class SampleTask extends TimerTask{ 字串2private static final int C_SCHEDULE_HOUR = 23;//设置指定时间private WorkService workService;private List users;private List teams;private WorkPortlet work;public void setWorkService(WorkService workService) {this.workService = workService;} 字串7public void setWork(WorkPortlet work) {this.work = work;} 字串4public SampleTask(){}@SuppressWarnings("unchecked")public void run() {Calendar cal = Calendar.getInstance();try {users = work.getUsers();teams = new ArrayList();for(Iterator it = users.iterator(); it.hasNext();){String teamname = work.getGroupsByUser((String)it.next()); teams.add(teamname);}//查看当前时间与指定是否一致,一致则执行任务if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY) ) 字串6workService.autoWorkOff(users, teams); 字串8} catch (SecurityException e) {e.printStackTrace();}}}使用Quartz定时<bean id="methodInvokingJobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject"><ref bean="changeService"/></property><property name="targetMethod"><value>changeAll</value></property></bean><bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"><ref bean="methodInvokingJobDetail"/></property><property name="cronExpression"><!--<value>0 0 6,12,20 * * ?</value>--><value>0 0 23 * * ?</value></property></bean><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref local="cronTrigger"/></list></property></bean>简单定时<bean id="methodInvokingJobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject"><ref bean="sgService"/></property><property name="targetMethod"><value>updateNowSgList</value></property></bean><bean id="simpleTrigger"class="org.springframework.scheduling.quartz.SimpleTriggerBean"><property name="jobDetail"><ref bean="methodInvokingJobDetail"/></property><property name="startDelay"><value>10000</value> <!-- 10 s--></property><property name="repeatInterval"><value>1296000000</value> <!-- 1296000000 6 hours--></property></bean><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref local="simpleTrigger"/></list></property></bean>一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
定时任务任务的三种⽅法1,spring整合quartz⽅式,这种⽹上资料太多,简单引⽤⼀下就ok。
<bean id="taskJob" class="com.tyyd.dw.task.DataConversionTask"/><bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="group" value="job_work"/><property name="name" value="job_work_name"/><!--false表⽰等上⼀个任务执⾏完后再开启新的任务--><property name="concurrent" value="false"/><property name="targetObject"><ref bean="taskJob"/></property><property name="targetMethod"><value>run</value></property></bean><!-- 调度触发器 --><bean id="myTrigger"class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="name" value="work_default_name"/><property name="group" value="work_default"/><property name="jobDetail"><ref bean="jobDetail"/></property><property name="cronExpression"><value>0/5 * * * * ?</value></property></bean><!-- 调度⼯⼚ --><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref bean="myTrigger"/></list></property></bean>2.spring task⽅式的定时任务(最为简单,功能也简单)<!-- 定时器配置开始--><bean id="task1" class="com.XXX.Task1"></bean><bean id="task2" class="com.XXX.Task2"></bean><task:scheduled-tasks><task:scheduled ref="task1" method="execute" cron="0 */1 * * * ?"/><task:scheduled ref="task2" method="execute" cron="0 */1 * * * ?"/></task:scheduled-tasks><!-- 定时器配置结束-->使⽤的时候,直接写⼀个类,⼀个⽅法就可以了,简单快捷。
【spring-boot】springboot整合quartz实现定时任务在做项⽬时有时候会有定时器任务的功能,⽐如某某时间应该做什么,多少秒应该怎么样之类的。
spring⽀持多种定时任务的实现。
我们来介绍下使⽤spring的定时器和使⽤quartz定时器 1.我们使⽤spring-boot作为基础框架,其理念为零配置⽂件,所有的配置都是基于注解和暴露bean的⽅式。
2.使⽤spring的定时器: spring⾃带⽀持定时器的任务实现。
其可通过简单配置来使⽤到简单的定时任务。
@Component@Configurable@EnableSchedulingpublic class ScheduledTasks{@Scheduled(fixedRate = 1000 * 30)public void reportCurrentTime(){System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat ().format (new Date ()));}//每1分钟执⾏⼀次@Scheduled(cron = "0 */1 * * * * ")public void reportCurrentByCron(){System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));}private SimpleDateFormat dateFormat(){return new SimpleDateFormat ("HH:mm:ss");}}没了,没错,使⽤spring的定时任务就这么简单,其中有⼏个⽐较重要的注解: @EnableScheduling:标注启动定时任务。
springboot整合quartz集群环境实现动态定时任务配置【原】/*** 设置quartz属性** @author XW* @create_date 2016年12月28日* @return Properties*/public Properties quartzProperties() {Properties prop = new Properties();// org.quartz.scheduler.instanceName属性可为任何值,用在JDBC JobStore// 中来唯一标识实例,但是所有集群节点中必须相同。
prop.put("quartz.scheduler.instanceName", "ServerScheduler");// instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。
prop.put("org.quartz.scheduler.instanceId", "AUTO");//// Quartz内置了一个“更新检查”特性,因此Quartz项目每次启动后都会检查官网,Quartz是否存在新版本。
这个检查是异步的,不影响Quartz项目本身的启动和初始化。
// 设置org.quartz.scheduler.skipUpdateCheck的属性为true 来跳过更新检查prop.put("org.quartz.scheduler.skipUpdateCheck", "false");//prop.put("org.quartz.scheduler.jobFactory.class","org.quartz.simpl.SimpleJobFactory");// org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。
1、Scheduler的配置说明:Scheduler包含一个Trigger列表,每个Trigger表示一个作业。
2、Trigger的配置说明:1)Cron表达式的格式:秒分时日月周年(可选)。
字段名允许的值允许的特殊字符秒0-59 , - * /分0-59 , - * /小时0-23 , - * /日1-31 , - * ? / L W C月1-12 or JAN-DEC , - * /周几1-7 or SUN-SAT , - * ? / L C #年(可选字段) empty, 1970-2099 , - * /“?”字符:表示不确定的值“,”字符:指定数个值“-”字符:指定一个值的范围“/”字符:指定一个值的增加幅度。
n/m表示从n开始,每次增加m“L”字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X“W”字符:指定离给定日期最近的工作日(周一到周五)“#”字符:表示该月第几个周X。
6#3表示该月第3个周五2)Cron表达式范例:每隔5秒执行一次:*/5 * * * * ?每隔1分钟执行一次:0 */1 * * * ?每天23点执行一次:0 0 23 * * ?每天凌晨1点执行一次:0 0 1 * * ?每月1号凌晨1点执行一次:0 0 1 1 * ?每月最后一天23点执行一次:0 0 23 L * ?每周星期天凌晨1点实行一次:0 0 1 ? * L在26分、29分、33分执行一次:0 26,29,33 * * * ?每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?3、JobDetail的配置4、业务类的配置<bean id="testJob" class="com.cjm.web.service.quartz.TestJob"/>5、业务类源代码说明:业务类不需要继承任何父类,也不需要实现任何接口,只是一个普通的java类。
q1 2 3<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans" xmlns:xsi="http://www.w3 xsi:schemaLocation="/schema/beans http://www.springf4 5 6 7 8 9 10 11 12 13 14 15default-lazy-init="false"><!-- 调度器 --><bean name="schedulerFactoryBean" class="org.springframework.scheduling.quartz.<!-- 通过applicationContextSchedulerContextKey属性配置spring上下文 --> <property name="applicationContextSchedulerContextKey"><value>applicationContext</value></property></bean><!--加载可执行的任务--><bean id="loadTask" class="com.quartz.LoadTask" init-method="initTask" /></beans>1 2 3 4<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:quartz-task.xml</param-value></context-param>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19public class LoadTask {public void initTask() throws Exception {Scheduler scheduler = schedulerFactoryBean.getScheduler(); // 可执行的任务列表Collection<Task> taskList = taskService.findTask();for (Task task : taskList) {// 任务名称和任务组设置规则:// 名称:task_1 ..// 组:group_1 ..TriggerKey triggerKey = TriggerKey.triggerKey("task_" + task.getId(), "group_" + task.getId());CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);// 不存在,创建一个if (null == trigger) {JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withIdentity("task_" + task.getId(),"group_" + task.getId()).build();20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47jobDetail.getJobDataMap().put("scheduleJob", task);// 表达式调度构建器CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule(getCronExpression());// 按新的表达式构建一个新的triggertrigger = TriggerBuilder.newTrigger().withIdentity("task_" + task.getId(),"group_" + task.getId()).withSchedule(scheduleBuilder).build();scheduler.scheduleJob(jobDetail, trigger);} else {// trigger已存在,则更新相应的定时设置CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule(taskService.getCronExpression());// 按新的cronExpression表达式重新构建triggertrigger = trigger.getTriggerBuilder().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build();// 按新的trigger重新设置job执行scheduler.rescheduleJob(triggerKey, trigger);}}}@Autowiredprivate SchedulerFactoryBean schedulerFactoryBean;@Autowiredprivate TaskService taskService;}1 2 3 4 5 6 7 8 9 10 11public class QuartzTaskFactory implements Job {@Overridepublic void execute(JobExecutionContext context)throws JobExecutionException {// TODO Auto-generated method stubtry {System.out.println("任务运行...");Task task = (Task) context.getMergedJobDataMap().get( "scheduleJob");System.out.println("任务名称: [" + task.getTaskName() + "]");12 13 14 15 16 17//在这里执行你的任务...} catch (Exception e) {e.printStackTrace();}}}1 2 3Scheduler scheduler = schedulerFactoryBean.getScheduler();JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.pauseJob(jobKey);1 2 3Scheduler scheduler = schedulerFactoryBean.getScheduler();JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());scheduler.resumeJob(jobKey);1 2 3Scheduler scheduler = schedulerFactoryBean.getScheduler();JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.deleteJob(jobKey);1 2 3Scheduler scheduler = schedulerFactoryBean.getScheduler();JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.triggerJob(jobKey);12Scheduler scheduler = schedulerFactoryBean.getScheduler();3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());//获取trigger,即在spring配置文件中定义的 bean id="myTrigger"CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);//表达式调度构建器CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob .getCronExpression());//按新的cronExpression表达式重新构建triggertrigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();//按新的trigger重新设置job执行scheduler.rescheduleJob(triggerKey, trigger);四、时间表达式说明。
Quartz spring 定时任务开发初步主要参考:、SchedulerFactoryBean会自动启动。
当在spring文件中定义了多个SchedulerFactoryBean实例时,一定要小心,因为这些ScheduleFactoryBean自从load进程序里,就会自动启动。
如果要手动控制,注意要将autoStartup属性设置为false。
2、SchedulerFactoryBean暴露的是Scheduler,而不是SchedulerFactoryBean。
SchedulerFactoryBean实现了FactoryBean接口,必须实现两个方法,一个是getObjectType,另外一个则是getObject;其中getObjectType定义了返回的类型应该为Scheduler,而getObject指定了返回的是其一个重要属性scheduler,这个scheduler就是我们要获得的调度。
若在配置文件里为SchedulerFactoryBean定义了id属性为"scheduler",则在程序里调用getBean时,需要注意getBean("scheduler")返回的是Scheduler对象3、SchedulerFactoryBean中有两个很重要的属性,一个是scheduler,另外一个是schedulerFactoryClass,spring通过用schedulerFactoryClass做代理来产生调度,并把它赋给scheduler。
private Class schedulerFactoryClass=StdSchedulerFactory.class;//如果你没有指定schedulerFactoryClass,那么它用的是quartz中自带的调度工厂,this.scheduler=createScheduler(schedulerFactory,this.schedulerNam e);//这里的schedulerName默认传进来是空的,其实如果你不是用自己定义的schedulerFactoryClass//恐怕也没有什么意义,因为createScheduler是这样调用的return schedulerFactory.getScheduler();//显然schedulerName并没有用到,除非是你自行写一个schedulerFactory,并做好相应处理,//否则返回的这个scheduler一定是一个指定名称的调度Scheduler sched=schedRep.lookup(getSchedulerName());//这个sched就是要代理生成的scheduler,getSchedulerName只有一句话,如下:cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,"QuartzScheduler");//如果我们没有使用一些特殊的机制,那么返回的只能是一个固定的字符串。
SpringBoot整合Quartz定时任务的简单实例POM.XML⽂件<!-- 定时器任务 quartz需要导⼊的坐标 --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>1.8.5</version></dependency>类似于控制器代码:package com.xiaowu.quartz.demo;import java.util.Date;import org.springframework.scheduling.annotation.Scheduled;import ponent;/***** Quartz设置项⽬全局的定时任务** @Component注解的意义泛指组件,当组件不好归类的时候,我们可以使⽤这个注解进⾏标注。
⼀般公共的⽅法我会⽤上这个注解*** @author WQ**/@Componentpublic class QuartzDemo {@Scheduled(cron = "0 0/1 * * * ?") // 每分钟执⾏⼀次public void work() throws Exception {System.out.println("执⾏调度任务:"+new Date());}@Scheduled(fixedRate = 5000)//每5秒执⾏⼀次public void play() throws Exception {System.out.println("执⾏Quartz定时器任务:"+new Date());}@Scheduled(cron = "0/2 * * * * ?") //每2秒执⾏⼀次public void doSomething() throws Exception {System.out.println("每2秒执⾏⼀个的定时任务:"+new Date());}@Scheduled(cron = "0 0 0/1 * * ? ") // 每⼀⼩时执⾏⼀次public void goWork() throws Exception {System.out.println("每⼀⼩时执⾏⼀次的定时任务:"+new Date());}}启动SpringBoot项⽬,即可。
spring多个定时任务quartz配置spring多个定时任务quartz配置2010-12-08 1034 A.M.xmlversion1.0encodingUTF-8 beans xmlns beanidjob1classcom.job.Job1///任务1 beanidjob2classcom.job.Job2///任务2 bean idjobDetail_1 classorg.springframework.scheduling.quartz.MethodInvokingJo bDetailFactoryBean property nametargetObject ref beanjob1/ /property property nametargetMethod value jobMethod1/value//执行的方法/property /bean bean idjobDetail_2classorg.springframework.scheduling.quartz.MethodInvokingJo bDetailFactoryBean property nametargetObject ref beanjob2/ /property property nametargetMethod value jobMethod2/value /property /bean bean idcronTrigger_1classorg.springframework.scheduling.quartz.CronTriggerBean property namejobDetail ref beanjobDetail_1/ /property property namecronExpression value 00 0/value//每天凌晨12点执行一次/property /bean bean idcronTrigger_2classorg.springframework.scheduling.quartz.CronTriggerBean property namejobDetail ref beanjobDetail_2/ /property property namecronExpression value 00/1/value//每小时执行一次/property /bean beanclassorg.springframework.scheduling.quartz.SchedulerFactoryBean property nametriggers list ref localcronTrigger_1/ ref localcronTrigger_2/ /list /property /bean /beans 一个cronExpression表达式有至少6个也可能是7个由空格分隔的时间元素。
springboot整合Quartz实现动态配置定时任务版权声明:本⽂为博主原创⽂章,转载请注明出处。
https:///liuchuanhong1/article/details/60873295前⾔在我们⽇常的开发中,很多时候,定时任务都不是写死的,⽽是写到数据库中,从⽽实现定时任务的动态配置,下⾯就通过⼀个简单的⽰例,来实现这个功能。
⼀、新建⼀个springboot⼯程,并添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><!-- 为了⽅便测试,此处使⽤了内存数据库 --><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version><exclusions><exclusion><artifactId>slf4j-api</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions></dependency><dependency><!-- 该依赖必加,⾥⾯有sping对schedule的⽀持 --><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency>⼆、配置⽂件application.properties# 服务器端⼝号server.port=7902# 是否⽣成ddl语句spring.jpa.generate-ddl=false# 是否打印sql语句spring.jpa.show-sql=true# ⾃动⽣成ddl,由于指定了具体的ddl,此处设置为nonespring.jpa.hibernate.ddl-auto=none# 使⽤H2数据库spring.datasource.platform=h2# 指定⽣成数据库的schema⽂件位置spring.datasource.schema=classpath:schema.sql# 指定插⼊数据库语句的脚本位置spring.datasource.data=classpath:data.sql# 配置⽇志打印信息logging.level.root=INFO.hibernate=INFO.hibernate.type.descriptor.sql.BasicBinder=TRACE.hibernate.type.descriptor.sql.BasicExtractor=TRACE.itmuch=DEBUG三、Entity类package com.chhliu.springboot.quartz.entity;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;@Entitypublic class Config {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Columnprivate String cron;/*** @return the id*/public Long getId() {return id;}……此处省略getter和setter⽅法……}四、任务类package com.chhliu.springboot.quartz.entity;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableScheduling;import ponent;@Configuration@Component // 此注解必加@EnableScheduling // 此注解必加public class ScheduleTask {private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleTask.class);public void sayHello(){("Hello world, i'm the king of the world");}}五、Quartz配置类由于springboot追求零xml配置,所以下⾯会以配置Bean的⽅式来实现package com.chhliu.springboot.quartz.entity;import org.quartz.Trigger;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.quartz.CronTriggerFactoryBean;import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;import org.springframework.scheduling.quartz.SchedulerFactoryBean;@Configurationpublic class QuartzConfigration {/*** attention:* Details:配置定时任务*/@Bean(name = "jobDetail")public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduleTask task) {// ScheduleTask为需要执⾏的任务 MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();/** 是否并发执⾏* 例如每5s执⾏⼀次任务,但是当前任务还没有执⾏完,就已经过了5s了,* 如果此处为true,则下⼀个任务会执⾏,如果此处为false,则下⼀个任务会等待上⼀个任务执⾏完后,再开始执⾏ */jobDetail.setConcurrent(false);jobDetail.setName("srd-chhliu");// 设置任务的名字jobDetail.setGroup("srd");// 设置任务的分组,这些属性都可以存储在数据库中,在多任务的时候使⽤/** 为需要执⾏的实体类对应的对象*/jobDetail.setTargetObject(task);/** sayHello为需要执⾏的⽅法* 通过这⼏个配置,告诉JobDetailFactoryBean我们需要执⾏定时执⾏ScheduleTask类中的sayHello⽅法*/jobDetail.setTargetMethod("sayHello");return jobDetail;}/*** attention:* Details:配置定时任务的触发器,也就是什么时候触发执⾏定时任务*/@Bean(name = "jobTrigger")public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) { CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();tigger.setJobDetail(jobDetail.getObject());tigger.setCronExpression("0 30 20 * * ?");// 初始时的cron表达式tigger.setName("srd-chhliu");// trigger的namereturn tigger;}/*** attention:* Details:定义quartz调度⼯⼚*/@Bean(name = "scheduler")public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) {SchedulerFactoryBean bean = new SchedulerFactoryBean();// ⽤于quartz集群,QuartzScheduler 启动时更新⼰存在的Jobbean.setOverwriteExistingJobs(true);// 延时启动,应⽤启动1秒后bean.setStartupDelay(1);// 注册触发器bean.setTriggers(cronJobTrigger);return bean;}}六、定时查库,并更新任务package com.chhliu.springboot.quartz.entity;import javax.annotation.Resource;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.Scheduled;import ponent;import com.chhliu.springboot.quartz.repository.ConfigRepository;@Configuration@EnableScheduling@Componentpublic class ScheduleRefreshDatabase {@Autowiredprivate ConfigRepository repository;@Resource(name = "jobDetail")private JobDetail jobDetail;@Resource(name = "jobTrigger")private CronTrigger cronTrigger;@Resource(name = "scheduler")private Scheduler scheduler;@Scheduled(fixedRate = 5000) // 每隔5s查库,并根据查询结果决定是否重新设置定时任务public void scheduleUpdateCronTrigger() throws SchedulerException {CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());String currentCron = trigger.getCronExpression();// 当前Trigger使⽤的String searchCron = repository.findOne(1L).getCron();// 从数据库查询出来的System.out.println(currentCron);System.out.println(searchCron);if (currentCron.equals(searchCron)) {// 如果当前使⽤的cron表达式和从数据库中查询出来的cron表达式⼀致,则不刷新任务} else {// 表达式调度构建器CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);// 按新的cronExpression表达式重新构建triggertrigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()).withSchedule(scheduleBuilder).build();// 按新的trigger重新设置job执⾏scheduler.rescheduleJob(cronTrigger.getKey(), trigger);currentCron = searchCron;}}}六、相关脚本1、data.sqlinsert into config(id,cron) values(1,'0 0/2 * * * ?'); # 每2分钟执⾏⼀次定时任务2、schema.sqldrop table config if exists;create table config(id bigint generated by default as identity,cron varchar(40),primary key(id));六、运⾏测试测试结果如下:(Quartz默认的线程池⼤⼩为10)0 30 20 * * ?0 0/2 * * * ?2017-03-08 18:02:00.025 INFO 5328 --- [eduler_Worker-1] c.c.s.quartz.entity.ScheduleTask : Hello world, i'm the king of the world2017-03-08 18:04:00.003 INFO 5328 --- [eduler_Worker-2] c.c.s.quartz.entity.ScheduleTask : Hello world, i'm the king of the world2017-03-08 18:06:00.002 INFO 5328 --- [eduler_Worker-3] c.c.s.quartz.entity.ScheduleTask : Hello world, i'm the king of the world2017-03-08 18:08:00.002 INFO 5328 --- [eduler_Worker-4] c.c.s.quartz.entity.ScheduleTask : Hello world, i'm the king of the world从上⾯的⽇志打印时间来看,我们实现了动态配置,最初的时候,任务是每天20:30执⾏,后⾯通过动态刷新变成了每隔2分钟执⾏⼀次。
浅谈SpringBoot集成Quartz动态定时任务SpringBoot⾃带schedule沿⽤的springboot少xml配置的优良传统,本⾝⽀持表达式等多种定时任务注意在程序启动的时候加上@EnableScheduling@Scheduled(cron="0/5 * * * * ?")public void job(){System.out.println("每五秒执⾏⼀次");}为什么要使⽤Quartz多任务情况下,quartz更容易管理,可以实现动态配置执⾏时间表达式:表达式⽰例:集成Quartz如何搭建springboot就不再细说,官⽹和⽹上的教程很多。
maven依赖<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency>测试Job类SchedulerQuartzJob1和SchedulerQuartzJob2代码差不多就不⼀⼀列出package com.yvan.quartz.job;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/*** 实现Job接⼝* @author yvan**/public class SchedulerQuartzJob1 implements Job{private void before(){System.out.println("任务开始执⾏");}@Overridepublic void execute(JobExecutionContext arg0) throws JobExecutionException {before();System.out.println("开始:"+System.currentTimeMillis());// TODO 业务System.out.println("结束:"+System.currentTimeMillis());after();}private void after(){System.out.println("任务开始执⾏");}}任务调⽤处理将其拆分成两个部分实例化Job,将任务触发器加⼊任务调度中private void startJob1(Scheduler scheduler) throws SchedulerException {// 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接⼝的实例// JobDetail 是具体Job实例JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob1.class).withIdentity("job1", "group1").build(); // 基于表达式构建触发器CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");// CronTrigger表达式触发器继承于Trigger// TriggerBuilder ⽤于构建触发器实例CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job1", "group1").withSchedule(cronScheduleBuilder).build();scheduler.scheduleJob(jobDetail, cronTrigger);}private void startJob2(Scheduler scheduler) throws SchedulerException {JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob2.class).withIdentity("job2", "group2").build(); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/5 * * * ?");CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job2", "group2").withSchedule(cronScheduleBuilder).build();scheduler.scheduleJob(jobDetail, cronTrigger);}对外提供关于动态管理任务的⽅法/*** 开始执⾏所有任务** @throws SchedulerException*/public void startJob() throws SchedulerException {startJob1(scheduler);startJob2(scheduler);scheduler.start();}/*** 获取Job信息** @param name* @param group* @return* @throws SchedulerException*/public String getJobInfo(String name, String group) throws SchedulerException {TriggerKey triggerKey = new TriggerKey(name, group);CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);return String.format("time:%s,state:%s", cronTrigger.getCronExpression(),scheduler.getTriggerState(triggerKey).name());}/*** 修改某个任务的执⾏时间** @param name* @param group* @param time* @return* @throws SchedulerException*/public boolean modifyJob(String name, String group, String time) throws SchedulerException {Date date = null;TriggerKey triggerKey = new TriggerKey(name, group);CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);String oldTime = cronTrigger.getCronExpression();if (!oldTime.equalsIgnoreCase(time)) {CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(cronScheduleBuilder).build();date = scheduler.rescheduleJob(triggerKey, trigger);}return date != null;}/*** 暂停所有任务** @throws SchedulerException*/public void pauseAllJob() throws SchedulerException {scheduler.pauseAll();}/*** 暂停某个任务** @param name* @param group* @throws SchedulerException*/public void pauseJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.pauseJob(jobKey);}/*** 恢复所有任务** @throws SchedulerException*/public void resumeAllJob() throws SchedulerException {scheduler.resumeAll();}/*** 恢复某个任务** @param name* @param group* @throws SchedulerException*/public void resumeJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.resumeJob(jobKey);}/*** 删除某个任务** @param name* @param group* @throws SchedulerException*/public void deleteJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.deleteJob(jobKey);}完整代码package com.yvan.quartz;import java.util.Date;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import com.yvan.quartz.job.SchedulerQuartzJob1;import com.yvan.quartz.job.SchedulerQuartzJob2;/*** 任务调度处理* @author yvan**/@Configurationpublic class QuartzScheduler {// 任务调度@Autowiredprivate Scheduler scheduler;/*** 开始执⾏所有任务** @throws SchedulerException*/public void startJob() throws SchedulerException {startJob1(scheduler);startJob2(scheduler);scheduler.start();}/*** 获取Job信息** @param name* @param group* @return* @throws SchedulerException*/public String getJobInfo(String name, String group) throws SchedulerException {TriggerKey triggerKey = new TriggerKey(name, group);CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);return String.format("time:%s,state:%s", cronTrigger.getCronExpression(),scheduler.getTriggerState(triggerKey).name());}/*** 修改某个任务的执⾏时间** @param name* @param group* @param time* @return* @throws SchedulerException*/public boolean modifyJob(String name, String group, String time) throws SchedulerException { Date date = null;TriggerKey triggerKey = new TriggerKey(name, group);CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);String oldTime = cronTrigger.getCronExpression();if (!oldTime.equalsIgnoreCase(time)) {CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(cronScheduleBuilder).build();date = scheduler.rescheduleJob(triggerKey, trigger);}return date != null;}/*** 暂停所有任务** @throws SchedulerException*/public void pauseAllJob() throws SchedulerException {scheduler.pauseAll();}/*** 暂停某个任务** @param name* @param group* @throws SchedulerException*/public void pauseJob(String name, String group) throws SchedulerException {JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.pauseJob(jobKey);}/*** 恢复所有任务** @throws SchedulerException*/public void resumeAllJob() throws SchedulerException {scheduler.resumeAll();}/*** 恢复某个任务** @param name* @param group* @throws SchedulerException*/public void resumeJob(String name, String group) throws SchedulerException {JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.resumeJob(jobKey);}/*** 删除某个任务** @param name* @param group* @throws SchedulerException*/public void deleteJob(String name, String group) throws SchedulerException {JobKey jobKey = new JobKey(name, group);JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (jobDetail == null)return;scheduler.deleteJob(jobKey);}private void startJob1(Scheduler scheduler) throws SchedulerException {// 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接⼝的实例// JobDetail 是具体Job实例JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob1.class).withIdentity("job1", "group1").build(); // 基于表达式构建触发器CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");// CronTrigger表达式触发器继承于Trigger// TriggerBuilder ⽤于构建触发器实例CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job1", "group1").withSchedule(cronScheduleBuilder).build();scheduler.scheduleJob(jobDetail, cronTrigger);}private void startJob2(Scheduler scheduler) throws SchedulerException {JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob2.class).withIdentity("job2", "group2").build(); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/5 * * * ?");CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job2", "group2").withSchedule(cronScheduleBuilder).build();scheduler.scheduleJob(jobDetail, cronTrigger);}}Scheduler 注⼊这⾥采⽤监听spring容器加载完毕后事件,启动任务调⽤将Scheduler交给spring初始化管理package com.yvan.quartz;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.impl.StdSchedulerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.event.ContextRefreshedEvent;@Configurationpublic class ApplicationStartQuartzJobListener implements ApplicationListener<ContextRefreshedEvent>{@Autowiredprivate QuartzScheduler quartzScheduler;/*** 初始启动quartz*/@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {try {quartzScheduler.startJob();System.out.println("任务已经启动...");} catch (SchedulerException e) {e.printStackTrace();}}/*** 初始注⼊scheduler* @return* @throws SchedulerException*/@Beanpublic Scheduler scheduler() throws SchedulerException{SchedulerFactory schedulerFactoryBean = new StdSchedulerFactory();return schedulerFactoryBean.getScheduler();}}封装API这⾥封装的API主要是为了⽅便动态管理执⾏任务,当然依赖这些接⼝也可以做⼀个界⾯来更直观的操作管理任务,这个就不再赘述。