文章目录
- 前言
-
- 基于quartz,刷新定时器的cron表达式
-
- [1. 先看一下测试效果](#1. 先看一下测试效果)
- [2. 实现代码](#2. 实现代码)
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
基于quartz,刷新定时器的cron表达式
1. 先看一下测试效果
因为这个我是基于quartz里面部分功能做的自定义分布式定时器框架,因此,关于定时器的实现可以略过,下面是我这个测试任务定时器的定义,看看就好。
java
@Bean(name = "testFourTaskDetail")
public JobDetail testFourTaskDetail(MyTask myTask) throws ClassNotFoundException, NoSuchMethodException {
MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
jobDetailFactoryBean.setConcurrent(Boolean.TRUE);
jobDetailFactoryBean.setName("testFourTask");
jobDetailFactoryBean.setTargetObject(myTask);
jobDetailFactoryBean.setTargetMethod("testFourTask");
jobDetailFactoryBean.afterPropertiesSet();
return jobDetailFactoryBean.getObject();
}
//定时触发器
@Bean(name = "testFourTaskTrigger")
public CronTriggerFactoryBean testFourTaskTrigger(@Qualifier("testFourTaskDetail") JobDetail testTwoTaskDetail){
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(testTwoTaskDetail);
//初始的Cron表达式
//cronTriggerFactoryBean.setCronExpression("0 0/15 * * * ?");
cronTriggerFactoryBean.setCronExpression("* * * * * ?");
return cronTriggerFactoryBean;
}
//Quartz 调度工厂
@Bean("scheduler")
public SchedulerFactoryBean schedulerFactoryBean(
@Qualifier("testFourTaskTrigger") Trigger testFourTaskTrigger
){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setOverwriteExistingJobs(true); // 如果存在重复的任务,会覆盖
// 延迟启动 1s
schedulerFactoryBean.setStartupDelay(1);
// 配置线程池
Properties quartzProperties = new Properties();
quartzProperties.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
// 设置线程池大小为10 threadCount 决定了最多可以并行执行多少个任务,多个任务可以同时运行,互不阻塞。
quartzProperties.setProperty("org.quartz.threadPool.threadCount", "10");
quartzProperties.setProperty("org.quartz.threadPool.threadPriority", "5"); //线程优先级
schedulerFactoryBean.setQuartzProperties(quartzProperties);
//注册触发器
schedulerFactoryBean.setTriggers(
testFourTaskTrigger);
return schedulerFactoryBean;
}
下面是任务:
java
@SchedulerTaskLock(name = SchedulerTaskEnum.TEST_FOUR_TASK,
lockAtMostForString = 1000 * 6 * 5,
lockMostTimeForString = 1000 * 60 * 5,
saveLock = true,
saveType = SchedulerTask.ALL,
lockStatus = true
)
public void testFourTask() throws InterruptedException {
Thread.sleep(11000);
int[] numbers = {1, 2, 3};
System.out.println(numbers[3]);
log.info("============= testFourTask============");
SchedulerTaskUtils.updateChannelTag(TagEnum.ERROR_TAG,"testFourTask执行逻辑时出现错误");
SchedulerTaskUtils.updateChannelTag(TagEnum.SUCCESS_TAG);
}
下面是pom:
xml
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<!-- Quartz Scheduler -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
我这个任务是每秒执行一次,我这个任务是测试的下标越界异常捕获否示例,所有报错是很正常的,如下:
下面是执行刷新cron表达式的效果:
triggerKey是你的触发器的bean name,cronExpression是你要更新的cron表达式。
看下图,可以看到刷新成功了。
然后我们看它的执行频率:
明显不是每秒执行一次了。
2. 实现代码
下面是代码:
工具类:
java
package org.example.quartz;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.Resource;
/**
* @description: TODO
* @author 杨镇宇
* @date 2024/7/31 14:05
* @version 1.0
*/
@Configuration
@EnableScheduling
@Slf4j
public class SchedulerRefresh {
// 静态成员变量,存储Scheduler对象
private static Scheduler scheduler;
// 使用ApplicationContext注入Scheduler
@Autowired
public void setScheduler(Scheduler scheduler) {
SchedulerRefresh.scheduler = scheduler; // 将注入的Scheduler赋值给静态成员变量
}
public static boolean refresh(String triggerKey, String cronExpression) throws SchedulerException {
// 获取当前的 Trigger
TriggerKey key = TriggerKey.triggerKey(triggerKey);
CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(key);
if (null != oldTrigger) {
// 如果存在,创建一个新的 CronTrigger
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
CronTrigger newTrigger = oldTrigger.getTriggerBuilder()
.withSchedule(cronScheduleBuilder)
.build();
// 重新调度任务
scheduler.rescheduleJob(key, newTrigger);
log.info("已刷新Cron表达式,新的表达式为: {}", cronExpression);
return Boolean.TRUE;
} else {
log.warn("未找到指定的 Trigger: {}", triggerKey);
return Boolean.FALSE;
}
}
}
controller:
java
@ApiOperation(value = "刷新cron表达式", notes = "刷新cron表达式")
@CommonLog(methodName = "刷新cron表达式",className = "TSchedulerLockController#schedulerRefresh")
@RequestMapping(value = "/schedulerRefresh", method = RequestMethod.POST)
public ResponseResult schedulerRefresh(@Validated @RequestBody SchedulerRefreshVo searchParam){
boolean refreshRes;
try {
refreshRes = SchedulerRefresh.refresh(searchParam.getTriggerKey(),searchParam.getCronExpression());
}catch (SchedulerException sc){
log.error("定时器刷新cron失败",sc);
throw new RunException(ExceptionEnum.ERROR_MSG,"定时器刷新cron失败");
}
return ResponseResult.ok(refreshRes);
}
vo:
java
package org.example.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.hibernate.validator.constraints.NotEmpty;
/**
* @author 杨镇宇
* @date 2025/1/21 9:25
* @version 1.0
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class SchedulerRefreshVo {
@ApiModelProperty("triggerKey")
@NotEmpty(message ="triggerKey不能为空")
private String triggerKey;
@ApiModelProperty("cronExpression")
@NotEmpty(message ="cronExpression不能为空")
private String cronExpression;
}