Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
第一步、导包,导入quartz包
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.7</version>
</dependency>
<!--定时任务quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>我代码中用到了 hutool 的工具类
第二步、数据库建表,使用quartz给我们的sql文件建表
在IDEA中双击 shift 键 搜索table_mysql

点进去复制sql语句在navicat执行,执行后数据库表如下

第三步、创建配置类,主要是往IOC容器注入Scheduler
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.annotation.Resource;
/**
* 定时任务配置类
*/
@Configuration
public class ScheduleConfig {
@Resource
private SchedulerFactoryBean schedulerFactoryBean;
@Bean
public Scheduler scheduler() {
return schedulerFactoryBean.getScheduler();
}
}第四步、创建Job,这是定时任务工作的内容
import org.springframework.data.redis.core.RedisTemplate;
@DisallowConcurrentExecution //不允许并发执行
public class AmazonDataCaptureJob implements Job {
private static final Logger log = LoggerFactory.getLogger(AmazonDataCaptureJob.class);
@Resource
private RedisTemplate redisTemplate;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 定时任务需要执行的逻辑
}
}第五步、创建DTO,这个可以自己定义
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class ScheduleInfoDto implements Serializable {
@ApiModelProperty(value = "服务名称")
private String serveName;
@ApiModelProperty(value = "任务描述")
private String descName;
@ApiModelProperty(value = "任务名称")
private String jobName;
@ApiModelProperty(value = "任务组")
private String jobGroup;
@ApiModelProperty(value = "任务路径")
private String jobClassName;
@ApiModelProperty(value = "调度器名称")
private String triggerName;
@ApiModelProperty(value = "调度器组")
private String triggerGroup;
@ApiModelProperty(value = "表达式")
private String cronExpression;
@ApiModelProperty(value = "附加参数,会传给定时任务接口")
private String extras;
/**
* 状态 :
NONE,
NORMAL,
PAUSED,
COMPLETE,
ERROR,
BLOCKED;
*/
private String triggerState;
}
第六步、创建接口,主要有添加、修改、暂停、恢复、获取所有任务接口
import com.sifan.erp.dto.ScheduleInfoDto;
import java.util.List;
public interface ScheduleService {
/**
* 添加定时任务Job
*
*/
void addSchedule(ScheduleInfoDto dto);
void executeOnce(String jobName, String jobGroup);
/**
* 暂停定时任务
*
* @param jobName
* @param jobGroup
*/
void pauseSchedule(String jobName, String jobGroup);
/**
* 恢复定时任务
*
* @param jobName
* @param jobGroup
*/
void resumeSchedule(String jobName, String jobGroup);
/**
* 更新定时任务
*
*/
void updateSchedule(ScheduleInfoDto dto);
/**
* 删除定时任务
*
* @param jobName
* @param jobGroup
*/
void deleteSchedule(String jobName, String jobGroup);
/**
* 获取所有的定时任务*
* @return 定时任务列表
*/
List<ScheduleInfoDto> getAllSchedule();
}
第七步、接口的实现类
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sifan.erp.dto.ScheduleInfoDto;
import com.sifan.erp.service.ScheduleService;
import lombok.SneakyThrows;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Service
public class ScheduleServiceImpl implements ScheduleService {
private static final Logger log = LoggerFactory.getLogger(ScheduleServiceImpl.class);
@Resource
private Scheduler scheduler;
/**
* 添加定时任务Job
*/
@SneakyThrows
@Override
public void addSchedule(ScheduleInfoDto dto) {
JobKey jobKey = new JobKey(dto.getJobName(), dto.getJobGroup());
//检查任务key是否存在
if (scheduler.checkExists(jobKey)) {
log.warn("该任务名称及任务组已存在!");
return ;
}
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("serveName", dto.getServeName());
if (ObjectUtil.isNotEmpty(dto.getExtras())) {
jobDataMap.put("extras", dto.getExtras());
}
//如果不传Job的话直接使用默认的Job
if (StrUtil.isEmpty(dto.getJobClassName())) {
dto.setJobClassName("com.sifan.erp.common.AmazonDataCaptureJob");
}
if (StrUtil.isEmpty(dto.getTriggerName())) {
dto.setTriggerName("jobTrigger" + IdUtil.fastSimpleUUID());
}
if (StrUtil.isEmpty(dto.getTriggerGroup())) {
dto.setTriggerGroup("jobTriggerGroup" + IdUtil.fastSimpleUUID());
}
try {
JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(dto.getJobClassName()))
.withIdentity(dto.getJobName(), dto.getJobGroup())
.usingJobData(jobDataMap)
.withDescription(dto.getDescName())
.storeDurably()
.build();
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(dto.getTriggerName(), dto.getTriggerGroup())
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(dto.getCronExpression()))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
log.info("任务添加成功,任务信息:{}",dto);
} catch (SchedulerException | ClassNotFoundException e) {
log.error("任务添加异常异常,{}",e);
}
}
/**
* 执行一次
*/
@Override
public void executeOnce(String jobName, String jobGroup) {
if (StrUtil.isEmpty(jobName) || StrUtil.isEmpty(jobGroup)) {
log.warn("该任务名称:{} 任务组:{} 不存在!",jobName,jobGroup);
return ;
}
try {
//执行任务
scheduler.triggerJob(JobKey.jobKey(jobName, jobGroup));
log.info("任务名:{},任务组:{} ,执行成功",jobName,jobGroup);
} catch (SchedulerException e) {
log.error("任务名:{},任务组:{},执行异常,{}",jobName,jobGroup,e);
}
}
/**
* 暂停定时任务
*
* @param jobName
* @param jobGroup
*/
@Override
public void pauseSchedule(String jobName, String jobGroup) {
try {
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
log.info("任务名:{},任务组:{} ,暂停成功",jobName,jobGroup);
} catch (SchedulerException e) {
log.error("任务名:{},任务组:{},暂停异常,{}",jobName,jobGroup,e);
}
}
/**
* 恢复定时任务
*
* @param jobName
* @param jobGroup
*/
@Override
public void resumeSchedule(String jobName, String jobGroup) {
try {
scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
log.info("任务名:{},任务组:{} ,恢复成功",jobName,jobGroup);
} catch (SchedulerException e) {
log.error("任务名:{},任务组:{},恢复异常,{}",jobName,jobGroup,e);
}
}
/**
* 更新定时任务
*/
@SneakyThrows
@Override
public void updateSchedule(ScheduleInfoDto dto) {
JobKey jobKey = new JobKey(dto.getJobName(), dto.getJobGroup());
//检查任务key是否存在
if (scheduler.checkExists(jobKey)) {
deleteSchedule(dto.getJobName(), dto.getJobGroup());
}
//按新的trigger重新设置job执行,重启触发器
addSchedule(dto);
log.info("任务更新成功:{}",dto);
}
/**
* 删除定时任务
*
* @param jobName
* @param jobGroup
*/
@Override
public void deleteSchedule(String jobName, String jobGroup) {
try {
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
log.info("任务名:{},任务组:{} ,删除成功",jobName,jobGroup);
} catch (SchedulerException e) {
log.error("任务名:{},任务组:{},删除异常,{}",jobName,jobGroup,e);
}
}
/**
* 获取所有定时任务*
* @return
*/
@Override
public List<ScheduleInfoDto> getAllSchedule() {
List<ScheduleInfoDto> list = new ArrayList<ScheduleInfoDto>();
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = null;
try{
jobKeys = scheduler.getJobKeys(matcher);
jobKeys.forEach(jobKey ->{
try {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
triggers.forEach(trigger ->{
ScheduleInfoDto scheduleInfoDto = new ScheduleInfoDto();
//获取任务名
scheduleInfoDto.setJobName(jobKey.getName());
//获取任务组
scheduleInfoDto.setJobGroup(jobKey.getGroup());
try {
//获取任务状态
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
scheduleInfoDto.setTriggerState(triggerState.name());
//获取任务表达式
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
scheduleInfoDto.setCronExpression(cronExpression);
}
} catch (SchedulerException e) {
log.error("获取所有定时任务TriggerState出错 {}",e);
}
list.add(scheduleInfoDto);
});
} catch (SchedulerException e) {
log.error("获取所有定时任务triggers出错 {}",e);
}
});
}catch (SchedulerException e){
log.error("获取所有定时任务jobKeys发生异常 ,{}",e);
}
return list;
}
}
第八步、测试
import com.sifan.erp.dto.ScheduleInfoDto;
import com.sifan.erp.service.ScheduleService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
@SpringBootTest
public class QuartzTest {
@Resource
private ScheduleService scheduleService;
@Test
public void testAddSchedule(){
ScheduleInfoDto scheduleInfoDto = new ScheduleInfoDto();
scheduleInfoDto.setJobGroup("LOL");
scheduleInfoDto.setJobName("寒冰射手");
scheduleInfoDto.setJobClassName("com.sifan.erp.common.AmazonDataCaptureJob");
scheduleInfoDto.setCronExpression("0 30 16 * * ?");
scheduleService.addSchedule(scheduleInfoDto);
}
@Test
public void testExecuteOnce() throws InterruptedException {
scheduleService.executeOnce("二郎犬","狗子组");
TimeUnit.SECONDS.sleep(1000);
}
@Test
public void testUdateSchedule(){
ScheduleInfoDto scheduleInfoDto = new ScheduleInfoDto();
scheduleInfoDto.setJobGroup("狗子组");
scheduleInfoDto.setJobName("哈巴狗");
scheduleInfoDto.setJobClassName("com.sifan.erp.common.AmazonDataCaptureJob");
scheduleInfoDto.setCronExpression("0 34 16 * * ?");
scheduleService.updateSchedule(scheduleInfoDto);
}
@Test
public void testGetAllSchedule(){
List<ScheduleInfoDto> allSchedule = scheduleService.getAllSchedule();
System.out.println(allSchedule);
}
@Test
public void testPauseSchedule(){
scheduleService.pauseSchedule("哈巴狗","狗子组");
}
@Test
public void testResumeSchedule(){
scheduleService.resumeSchedule("哈巴狗","狗子组");
}
}
版权声明:本文为qq_43657722原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。