Quartz是一个强大的开源作业调度库,它可以用来创建简单或复杂的计划任务,这些任务可以是短期的,也可以是长期运行的。Quartz允许开发者定义任务执行的时间表,并在指定时间自动执行任务。
Quartz框架包含多个核心组件,每个组件在作业调度中扮演特定的角色:
Job :表示要执行的任务,它是一个接口,开发者需要通过实现这个接口来定义任务的业务逻辑。
JobDetail :用于配置Job的实例,包括Job的类名、名称、组名以及JobDataMap(用于存储任务执行时需要的数据)。
Trigger :用于触发作业的执行。Quartz提供了多种类型的Trigger,如SimpleTrigger、CronTrigger等。
Scheduler :调度器,它负责监听所有触发器,决定哪个任务需要被执行,并且在触发器指示时执行相应的Job。
Quartz的工作流程如下:
创建一个Scheduler实例,它负责管理和调度所有的任务。
配置JobDetail和Trigger,这两个组件定义了任务何时以及如何执行。
将JobDetail和Trigger注册到Scheduler中,这样任务就可以被调度器管理了。
调度器开始工作,它监听所有注册的Trigger,当触发条件满足时,调度器调用相应的Job执行任务。
任务执行完成后,调度器等待下一个Trigger激活。
1.首先导入quartz定时计划任务依赖包pom.xml
<!-- 定时计划任务依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> <version>2.2.5.RELEASE</version> </dependency> <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>
2.要使用Quartz创建一个作业任务,首先需要定义一个Job类并实现Job接口:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.tehn.server;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.tehn.config.MqttProviderConfig;
import com.tehn.utils.PropertiesUtil;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
@Component
@EnableScheduling
public class MyHandlerJob implements Job {
private final Logger logger = LoggerFactory.getLogger(MyHandlerJob.class);
private static ArrayList<String> electrDictList = new ArrayList<>();
private String companyCode = "XIAMENPULUOTE";
@Resource
private MqttProviderConfig providerClient;
static {
electrDictList.add("a");
electrDictList.add("b");
electrDictList.add("c");
}
public MyHandlerJob() {
}
/**
* 定时计划任务执行任务逻辑
* @param content 任务上下文
* @throws JobExecutionException
*/
public void execute(JobExecutionContext content) throws JobExecutionException {
this.logger.info("<----------------------------------------SPD转发每分钟定时任务开始-------------------------------------------->");
try {
// 读取spd设备数据json文件data.json
File myFileObj = new File(new PropertiesUtil().getPropertieString("spd_data_file_path"));
if(myFileObj.exists()){
Scanner myFileReader = new Scanner(myFileObj);
String data = "";
while (myFileReader.hasNextLine()){
data += myFileReader.nextLine();
}
if(StringUtils.isNotEmpty(data)){
Map<String, Object> spdDataMap = JSON.parseObject(data, new TypeReference<Map<String, Object>>(){});
JSONArray current2Jsonarr = (JSONArray) MapUtils.getObject(spdDataMap, "current2");
logger.info("获取spd数据:{}", current2Jsonarr.toJSONString());
if(current2Jsonarr.size() > 0){
Iterator<JSONObject> iterator = current2Jsonarr.iterator();
while (iterator.hasNext()){
JSONObject obj = iterator.next();
String deveCode = obj.getString("id");
String forwardDeviceStr = new PropertiesUtil().getPropertieString("forward_spd_device");
ArrayList<String> forwardDeviceCodeList = new ArrayList<>(Arrays.asList(forwardDeviceStr.split(",")));
if(forwardDeviceCodeList.contains(deveCode)){
JSONArray currentsArr = obj.getJSONArray("currents");
if(currentsArr.size() > 2){
// 这里就是需要转发的spd设备了
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("device_code", deveCode);
Integer diType = obj.getBooleanValue("di") ? 1 : 0;
dataMap.put("di_type", diType);
dataMap.put("humidity", obj.getInteger("humidity"));
dataMap.put("temperature", obj.getInteger("temperature"));
dataMap.put("thunder", obj.getInteger("thunder"));
dataMap.put("measure_time", obj.getString("time"));
for (int i = 0; i < currentsArr.size(); i++) {
JSONObject currObj = currentsArr.getJSONObject(i);
dataMap.put("current2_" + electrDictList.get(i) + "_angle", currObj.getInteger("angle"));
dataMap.put("current2_" + electrDictList.get(i) + "_angle_initial", currObj.getInteger("angleInitial"));
dataMap.put("current2_" + electrDictList.get(i) + "_offset_amplitude", currObj.getInteger("offsetAmplitude"));
dataMap.put("current2_" + electrDictList.get(i) + "_offset_angle", currObj.getInteger("offsetAngle"));
dataMap.put("current2_" + electrDictList.get(i) + "_total", currObj.getBigDecimal("total"));
dataMap.put("current2_" + electrDictList.get(i) + "_total_initial", currObj.getBigDecimal("totalInitial"));
}
Map<String, Object> msgMap = new HashMap<>();
msgMap.put("pubTime", System.currentTimeMillis());
String topic = "/tyhtehn/spd/" + deveCode + "/" + companyCode + "/deviceData";
msgMap.put("pubTopic", topic);
msgMap.put("body", dataMap);
String jsonStr = JSONObject.toJSONString(msgMap);
logger.info("设备上报数据:{}", jsonStr);
providerClient.publish(0, true, topic, jsonStr);
}
}
}
}
}
// 关闭资源
myFileReader.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
logger.info("<----------------------------------------SPD转发每分钟定时任务结束-------------------------------------------->");
}
}
3.创建job工厂,可以直接复制源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.tehn.server;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
public JobFactory() {
}
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
this.capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
4.创建任务配置类,可以直接复制源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.tehn.server;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class JobConfigCreator {
@Autowired
JobFactory jobFactory;
private static final Logger logger = LoggerFactory.getLogger(JobConfigCreator.class);
private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
public JobConfigCreator() {
}
public void addJob(JobKey jobKey, Class cls, String time, JobDataMap jobDataMap) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
sched.setJobFactory(this.jobFactory);
JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobKey).usingJobData(jobDataMap).build();
CronTriggerImpl trigger = new CronTriggerImpl(jobKey.getName());
trigger.setCronExpression(time);
sched.scheduleJob(jobDetail, trigger);
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception var8) {
throw new RuntimeException(var8);
}
}
public void modifyJobTime(TriggerKey triggerKey, JobKey jobKey, JobDataMap jobDataMap, String time) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
CronTrigger trigger = (CronTrigger)sched.getTrigger(triggerKey);
if (trigger != null) {
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
JobDetail jobDetail = sched.getJobDetail(jobKey);
Class objJobClass = jobDetail.getJobClass();
this.removeJob(jobKey, triggerKey);
this.addJob(jobKey, objJobClass, time, jobDataMap);
}
}
} catch (Exception var10) {
throw new RuntimeException(var10);
}
}
public void removeJob(JobKey jobkey, TriggerKey triggerKey) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
sched.pauseTrigger(triggerKey);
sched.unscheduleJob(triggerKey);
sched.deleteJob(jobkey);
logger.debug("+ jobkey + " + triggerKey);
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
public void removeJobs(List<JobKey> jobkey, TriggerKey triggerKey) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
sched.pauseTrigger(triggerKey);
sched.unscheduleJob(triggerKey);
sched.deleteJobs(jobkey);
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
public boolean checkExistsJob(JobKey jobkey) {
boolean flag = false;
try {
Scheduler sched = gSchedulerFactory.getScheduler();
flag = sched.checkExists(jobkey);
return flag;
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
public void startJobs() {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
sched.start();
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
public void shutdownJobs() {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
}
5.最后在你应用启动类中配置启动该计划任务。我的是每分钟执行一条任务