扯皮:
Quartz是一个分布式任务调度框架,详细介绍请查询官网,避免误导大众。目前搜索结果被某些网站霸占,点击进去很难找到自己想要的结果。Spring本身也可以实现任务调度,简单的任务调度,可以用Spring的,复杂一点的只能使用Quartz了,网上的文章眼花缭乱,特别是很多恶心的网站复制来复制去,重复率那么高。
Springboot集成Quartz的步骤:
1. 添加Quartz依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
2. 实现Job类
@DisallowConcurrentExecution
public class ShellJob extends QuartzJobBean {
@Autowired
protected IWflowLaststatusTableService lastStatusService;
// 历史日志
@Autowired
protected IWflowLogTableService logService;
@Override
public void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("executeInternal...................");
// 约略了很多代码。
// 模板是这样是这样自,里面用到了Autowired.
}
}
如果直接实现Job接口,@Autowired永远只会返回null,别老折腾,QuartzJobBean实现了Job接口,除非你参照QuartzJobBean的实现,不然在Job里面用Autowired是不可能的。
3. 配置Quartz
spring:
quartz:
job-store-type: jdbc
properties:
org:
quartz:
scheduler:
instanceName: JobScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
useProperties: false
dontSetAutoCommitFalse: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 11
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
其中JobScheduler是实例的名字,相当于是集群名字,随便命名。
4. 添加任务调度器
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
@Component
public class JobSchedManageServiceImpl implements JobSchedManageService {
static final Logger logger = LoggerFactory.getLogger(JobSchedManageServiceImpl.class);
@Autowired
private Scheduler mSched = null;
// 省略了很多代码的
/**
* 启动任务调度 初始化调度
*
* @throws Exception
*/
@PostConstruct
public synchronized void start() {
try {
if (mSched == null) {
mSched = getSched();
}
// 添加任务监听
mSched.getListenerManager().addJobListener(logListener);
// 添加触发器监听
mSched.getListenerManager().addTriggerListener(jobTriggerListener);
// 添加调度监听器
mSched.getListenerManager().addSchedulerListener(jobSchedListener);
if (!mSched.isStarted()) {
mSched.start();
}
} catch (Exception e) {
logger.error("启动调度失败", e);
}
}
/**
* 添加调度任务
*
* @param jobClass 执行任务的类
* @param jobName 任务名称
* @param jobGroup 任务组
* @param entity 任务相关配置
* @throws Exception
*/
public synchronized void addJob(Class jobClass, String jobName, String jobGroup, JobSchedEntity entity)
throws Exception {
try {
if (mSched == null) {
mSched = getSched();
}
JobKey jobKey = new JobKey(jobName, jobGroup);
if (mSched.checkExists(jobKey)) {
mSched.deleteJob(jobKey);
}
//
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
jobDetail.getJobDataMap().put(JobSchedManageService.TASK_PROPERTIES, entity);
// 0:不执行 1:执行一次,2: CRON表达式 3:简单触发器
if (entity.getSchedType() == 0) {
mSched.addJob(jobDetail, true);
} else {
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup);
if (entity.getStartTime() != null) {
triggerBuilder.startAt(entity.getStartTime());
} else {
triggerBuilder.startNow();
}
if (entity.getEndTime() != null) {
triggerBuilder.endAt(entity.getEndTime());
}
if (entity.getSchedType() == 1) {
// simpletrigger
triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule());
} else {
// entity.getSchedType() == 2
// CRON表达式
if (entity.getCronExpr() != null && entity.getCronExpr().trim().length() >= 0) {
//错过的周期不在触发
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(entity.getCronExpr()).withMisfireHandlingInstructionDoNothing().inTimeZone(TimeZone.getTimeZone("Asia/Shanghai")));
} else {
// cron为空
triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionNextWithExistingCount());
}
}
Trigger trigger = triggerBuilder.build();
trigger.getJobDataMap().put(JobSchedManageService.WFLOW_ID,entity.getWflowId());
trigger.getJobDataMap().put(JobSchedManageService.TRIGGER_PROPERTIES, entity);
trigger.getJobDataMap().put(JobSchedManageService.SCHED_TYPE, ExecTypeEnum.PERIOD_EXEC.getValue());
mSched.scheduleJob(jobDetail, trigger);
}
} catch (Exception e) {
logger.error("add job catch exception:" + e.getMessage());
throw e;
}
}
}
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(entity.getCronExpr()).withMisfireHandlingInstructionDoNothing().inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))); 主要是确保时区的,不加的话,第一次执行会晚8个小时执行,其他代码就不贴了,已经把主要的贴出来了,上述代码仅供参考。