<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/> <property name="configLocation" value="classpath:quartz.properties"/> <!--这个是必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动--> <property name="startupDelay" value="30"/> <!--这个是可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了--> <property name="overwriteExistingJobs" value="true"/> <property name="jobDetails" > <list> <ref bean="jobDetail"/> <ref bean="jobDetail2"/> </list> </property> </bean> <bean id="jobDetail" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!--shouldRecover属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务--> <property name="shouldRecover" value="true"/> <property name="targetObject" ref="customerService"/> <property name="targetMethod" value="testMethod1"/> </bean> <bean id="jobDetail2" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!--shouldRecover属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务--> <property name="shouldRecover" value="true"/> <property name="targetObject" ref="customerService"/> <property name="targetMethod" value="testMethod2"/> </bean> </beans>
2.略
3.1.1
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="applicationContextSchedulerContextKey" value="applicationContextKey" /> <property name="configLocation" value="classpath:quartz.properties"/> </bean> <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass"> <value>com.sundoctor.example.service.MyQuartzJobBean</value> </property> </bean> </beans>
这里在MyQuartzJobBean中使用注解注入多个simpleService也可以
当我们调用Scheduler.scheduleJob(Trigger trigger)增加一个Trigger时quartz自己就会往库里插入数据了,对于Trigger数据的增删改都quartz本身持久化支持的,我们不用关心。
添加一个 simple Trigger时往qrtz_simple_triggers写一条记录,同时也会往qrtz_triggers写入一条记录,两个表根据trigger_name、trigger_group对应,开始时间存在qrtz_triggers表中,还有结束时间、上次执行时间、下次执行时间等都存在于qrtz_triggers表中。添加一个 cron Trigger时也一样,同时往qrtz_cron_triggers、qrtz_triggers各写入一条记录
3.1.2
<bean id="jobDetail1" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass"> <value>com.sundoctor.example.service.MyQuartzJobBean1</value> </property> <bean id="jobDetail2" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass"> <value>com.sundoctor.example.service.MyQuartzJobBean2</value> </property> <bean id="jobDetail3" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass"> <value>com.sundoctor.example.service.MyQuartzJobBean3</value> </property>
<util:map id = "jobDeatailMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="org.springframework.scheduling.quartz.JobDetailBean"> <entry key="jobDetail1" ref="jobDetail1"/> <entry key="jobDetail2" ref="jobDetail2"/> <entry key="jobDetail3" ref="jobDetail3"/> </util:map>
然后在SchedulerService 注入jobDeatailMap
@Service("schedulerService") public class SchedulerServiceImpl implements SchedulerService { private Scheduler scheduler; private Map<String,JobDetailBean> jobDeatailMap; @Autowired public void setJobDeatailMap(@Qualifier("jobDeatailMap") Map<String,JobDetailBean> jobDeatailMap) { this.jobDeatailMap = jobDeatailMap; } @Autowired public void setScheduler(@Qualifier("quartzScheduler") Scheduler scheduler) { this.scheduler = scheduler; } ...
最后,修改SchedulerServiceImpl中的schedule方法,增加以jobDeatailMap KEY名字为参数:
@Override public void schedule(String jobDetailName,String name, CronExpression cronExpression) { if (name == null || name.trim().equals("")) { name = UUID.randomUUID().toString(); } //这个时候JobDetail根据jobDetailName从jobDeatailMap获取 JobDetail jobDetail = jobDeatailMap.get(jobDetailName); try { scheduler.addJob(jobDetail, true); CronTrigger cronTrigger = new CronTrigger(name, Scheduler.DEFAULT_GROUP, jobDetail.getName(), Scheduler.DEFAULT_GROUP); cronTrigger.setCronExpression(cronExpression); scheduler.scheduleJob(cronTrigger); scheduler.rescheduleJob(name, Scheduler.DEFAULT_GROUP, cronTrigger); } catch (SchedulerException e) { throw new RuntimeException(e); } } 其它多态方法一样修改,增加jobDetailName参数。
调用时,传不同的jobDetailName参数就可以调用不用的JobDetail。
SchedulerService schedulerService = (SchedulerService)springContext.getBean("schedulerService");
schedulerService.schedule("jobDetail1","审计任务","0/10 * * ? * * *");
schedulerService.schedule("jobDetail2","发放任务","0/10 * * ? * * *");
schedulerService.schedule("jobDetail3","AAA任务","0/10 * * ? * * *");
其实很多时候只需要一个JobDetail就可以了,也可以达到多个JobDetail一样的效果,一个JobDetail的时候可以在Trigger名称上做扩展,可以在调度任务时给Trigger名称加上不同的前缀或后缀,比如Trigger名称增加一个前缀参数
@Override public void schedule(String name, String prefix ,CronExpression cronExpression) { if (name == null || name.trim().equals("")) { name = UUID.randomUUID().toString(); } try { scheduler.addJob(jobDetail, true); //给Trigger名秒加上前缀 name = prefix + name;
CronTrigger cronTrigger = new CronTrigger(name, Scheduler.DEFAULT_GROUP, jobDetail.getName(), Scheduler.DEFAULT_GROUP); cronTrigger.setCronExpression(cronExpression); scheduler.scheduleJob(cronTrigger); scheduler.rescheduleJob(name, Scheduler.DEFAULT_GROUP, cronTrigger); } catch (SchedulerException e) { throw new RuntimeException(e); } }
然后在QuartzJobBean中的executeInternal方法取到Trigger名秒,然后根据其前缀或后缀调用不同的业务逻辑
public class MyQuartzJobBean extends QuartzJobBean { private SimpleService simpleService; public void setSimpleService(SimpleService simpleService) { this.simpleService = simpleService; } @Override protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException { Trigger trigger = jobexecutioncontext.getTrigger(); //取得Trigger名称,判断名称前缀或后缀调用不同的业务逻辑 String triggerName = trigger.getName(); if(tirggerName ...){ simpleService.testMethod(triggerName); }else if(tirggerName ...){ simpleService.testMethod2(triggerName); }else{ ... } } }