先说结论
如果用的是quartz,那么要使用schedulerFactoryBean.rescheduleJob(),这个有效果;
而不是schedulerFactoryBean.resumeTrigger(),这个没有用,已测试。
扩展
使用rescheduleJob()后,该定时任务会立即执行一次;
可通过下面来进行设置不立即执行,按照corn表达式来执行;
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
https://blog.csdn.net/u010904188/article/details/80915760
-----------------------------------------------------------------------------
1.本人的项目是spring的,用到了quartz实现定时任务。
不过springboot中的实现思路应该也类似(虽然还没自己测试)
2.spring项目中quartz的依赖信息是:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
3.spring项目中,定时任务的xml配置如下,供参考:
<bean id="myScheduleJob" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<ref bean="myScheduleJobMethodBean"/>
</property>
<property name="cronExpression">
<!-- 每5分钟执行一次定时任务 -->
<value>0 0/5 * * * ?</value>
</property>
</bean>
<!-- 定时任务总管理类,如果将lazy-init设置为false,那么容器启动就会执行调度程序 -->
<bean id="startQuatz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- 使用了list标签,这里可以配置多个ref -->
<ref bean="myScheduleJob" />
</list>
</property>
</bean>
<bean id="myScheduleJobMethodBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<!-- 定时任务目标类 -->
<ref bean="myScheduleJobBean"/>
</property>
<property name="targetMethod">
<!-- 定时任务目标类中的方法,这个方法会定时执行 -->
<value>myScheduleMethod</value>
</property>
</bean>
<bean id="myScheduleJobBean" class="com.test.MyScheduleJobBean" >
<constructor-arg name="id" value="123" />
</bean>
4.定时任务的类MyScheduleJobBean.java,这个类中的方法myScheduleMethod会按照上方的配置定时执行,每5分钟执行一次:
public class MyScheduleJobBean {
private String id;
//可以通过构造器注入参数
public MyScheduleJobBean(String id){
this.id = id;
}
//这个方法会定时执行,需要为void,并且不能传入参数
public void myScheduleMethod(){
//省略具体内容
}
}
5.在代码中合适的位置写一个方法,比如写在Controller中;在项目启动后,调用Controller,就可以修改这个定时任务的执行周期了。方法如下:
//这个无法注入,可能是初始化未完成,详情不知道
//@Autowired
//CronTriggerFactoryBean myScheduleJob;
@Autowired
SchedulerFactoryBean startQuatz;
@Test
public void test(){
//所以这个不能用。
//myScheduleJob.setCronExpression("0 0/20 * * * ?");
//CronTrigger trigger = myScheduleJob.getObject();
//这个对应xml中配置的bean的id
TriggerKey myScheduleJob = TriggerKey.triggerKey("myscheduleJob");
Crontrigger trigger = (Crontrigger)startQuatz.getScheduler().getTrigger(myScheduleJob);
//可以查看旧的周期表达式,xml中配置的,[0 0/5 * * * ?]
String oldTime = trigger.getCronExpression();
//设置新的定时任务执行周期,每20分钟执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/20 * * * ?");
trigger = trigger.getTriggerBuilder().withIdentity(myScheduleJob).withSchedule(scheduleBuilder).build();
try{
//修改后,这个定时任务会立即执行一次
startQuatz.getScheduler().rescheduleJob(trigger.getKey(),trigger);
//这个没有效果,已测试,不能用
//startQuatz.getScheduler().resumeTrigger(trigger.getKey());
}
catch(SchedulerException e){
e.printStackTrace();
}
}
这里从spring容器中获取了startQuatz这两个对象,对应上面xml中配置的名字;(不过@Autowired是按类型注入的,在上方的例子中,没有重复的同类型bean了,所以可以注入)
使用rescheduleJob()修改定时任务执行周期后,该定时任务会立即执行一次。
如果不想让定时任务修改周期后立即执行一次,可以这样写:
//设置新的定时任务执行周期,每20分钟执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/20 * * * ?").withMisfireHandlingInstructionDoNothing();
注意,要使用rescheduleJob()才能修改定时任务执行周期。
下面这篇文章中用了resumeTrigger(),但是本人已测试这个方法不能修改定时任务执行周期。
https://vimsky.com/examples/detail/java-method-org.quartz.Scheduler.resumeTrigger.html