Quartz 使用记录

官网

https://www.quartz-scheduler.org/

参考文档

什么是 Quartz?

官方描述:

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.

翻译:
Quartz 是一个有丰富特性,开源任务调度库,能和任意(从单个小应用到大型系统.) Java 应用集成.Quartz 用于创建简单或者混合 调度器用于执行数以千计的任务.Quartz Scheduler 包含了很多企业级特性,例如支持 JTA.

单例使用

1.下载 Jar 包

下载地址 :https://www.quartz-scheduler.org/downloads/

或者 引入pom 依赖:

<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<!-- 日志简单实现 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.32</version>
<scope>compile</scope>
</dependency>

2. 将解压后lib文件夹下的 quartz-2.3.0-SNAPSHOT.jar 放于 Java 工程中

需下载 slf4j-simple.jar 包,否则使用SLF4j打印日志会报错:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

3. 配置 quartz.properties

在 classpath 添加 quartz.properties 文件,添加配置信息:

# 调度器名字
org.quartz.scheduler.instanceName = black-scheduler
# 线程池大小
org.quartz.threadPool.threadCount = 3
# 任务存储方式(RAMJobStore : 内存存储)
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

更详细配置参见 https://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration

4.编写HelloJob.java任务类

package org.black.demo.quartz;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date; import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class HelloJob implements Job{ private static final Logger LOGGER = LoggerFactory.getLogger(HelloJob.class); @Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOGGER.info("任务明细:{}", context.getJobDetail());
LOGGER.info("激活的实例ID{}",context.getFireInstanceId());
Date d =context.getFireTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOGGER.info("调度器:{}",context.getScheduler());
LOGGER.info("调度器激活时间:{}",f.format(context.getScheduledFireTime()));
if(context.getPreviousFireTime() != null) {
LOGGER.info("上次调用时间:{}",f.format(context.getPreviousFireTime()));
}
LOGGER.info("下次调用时间:{}",f.format(context.getNextFireTime()));
LOGGER.info("触发器:{}",context.getTrigger());
LOGGER.info("触发时间:{}", f.format(d));
LOGGER.info("job 实例:{}", context.getJobInstance());
LOGGER.info("job 运行时长:{}s", context.getJobRunTime());
LOGGER.info("Job 设置的返回结果:{}",context.getResult());
LOGGER.info("MergedJobDataMap:{}", context.getMergedJobDataMap());
//
// LOGGER.info("恢复任务时对应的触发器key:{}",context.getRecoveringTriggerKey());
LOGGER.info("重复激活次数:{}",context.getRefireCount()); LocalDateTime date = LocalDateTime.now();
String curDateTime = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LOGGER.info("时间:{},当前线程:{} - 执行 HelloJob 任务",curDateTime,Thread.currentThread().getName() );
}
}

5.编写 QuartzScheduleDemo 测试类

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Quartz 示例
*
* @author lihw
* @date 2021-12-27 17:48:011
*/
public class QuartzScheduleDemo { private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleDemo.class); public static void main(String[] args) {
try {
// 从工厂类获取调度器示例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动调度器
scheduler.start(); // 定义一个Job 绑定到 HelloJob.class
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build(); // 定义一个触发器,每 4s 执行一次任务
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever())
.build(); // 调度器调度任务
Date date = scheduler.scheduleJob(job, trigger);
LOGGER.info("Quartz 调度器启动时间:{}",date);
// 调用shutdown()方法关闭调度器,否则任务一直在运行
// scheduler.shutdown(); } catch (SchedulerException e) {
e.printStackTrace();
}
}
}

6.测试

测试结果:

[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'black-schedule' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered. [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'black-schedule' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.core.QuartzScheduler - Scheduler black-schedule_$_NON_CLUSTERED started.
[main] INFO org.black.demo.quartz.QuartzScheduleDemo - Quartz 调度器启动时间:Tue Dec 28 11:51:03 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 任务明细:JobDetail 'group1.job1': jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 激活的实例ID1640663463495
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 调度器:org.quartz.impl.StdScheduler@4a5fecdf
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 调度器激活时间:2021-12-28 11:51:03
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 下次调用时间:2021-12-28 11:51:07
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 触发器:Trigger 'group1.trigger1': triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:51:07 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 触发时间:2021-12-28 11:51:03
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 实例:org.black.demo.quartz.HelloJob@4dab129f
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 运行时长:-1s
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - Job 设置的返回结果:null
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 重复激活次数:0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:51:03,当前线程:black-schedule_Worker-1 - 执行 HelloJob 任务
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 任务明细:JobDetail 'group1.job1': jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 激活的实例ID1640663463496
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 调度器:org.quartz.impl.StdScheduler@4a5fecdf
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 调度器激活时间:2021-12-28 11:51:07
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 上次调用时间:2021-12-28 11:51:03
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 下次调用时间:2021-12-28 11:51:11
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 触发器:Trigger 'group1.trigger1': triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:51:11 CST 2021
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 触发时间:2021-12-28 11:51:07
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 实例:org.black.demo.quartz.HelloJob@5a318665
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 运行时长:-1s
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - Job 设置的返回结果:null
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 重复激活次数:0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:51:07,当前线程:black-schedule_Worker-2 - 执行 HelloJob 任务

Cron 表达式触发器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Quartz 示例
*
* @author lihw
* @date 2021-12-27 17:48:011
*/
public class QuartzScheduleCronTriggerDemo { private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleCronTriggerDemo.class); public static void main(String[] args) {
try {
// 从工厂类获取调度器示例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动调度器
scheduler.start(); // 定义一个Job 绑定到 HelloJob.class
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build(); // 定义一个触发器,每 10s 执行一次任务
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
// cron 表达式: 秒 分 时 日 月 周 年
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
.build(); // 调度器调度任务
Date date = scheduler.scheduleJob(job, trigger);
LOGGER.info("Quartz 调度器启动时间:{}",date);
// 调用shutdown()方法关闭调度器,否则任务一直在运行
// scheduler.shutdown(); } catch (SchedulerException e) {
e.printStackTrace();
}
}
}

withSchedule 方法可以设置不同的触发器类型.CronScheduleBuilder 继承自 ScheduleBuilder,ScheduleBuilder 的子类一共有4个,也就是可以设置 4中类型的触发器.

Calendar 触发器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.CalendarIntervalScheduleBuilder;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Quartz Calendar 触发器示例
*
* @author lihw
* @date 2021-12-27 17:48:011
*/
public class QuartzScheduleCalendarTriggerDemo { private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleCalendarTriggerDemo.class); public static void main(String[] args) {
try {
// 从工厂类获取调度器示例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动调度器
scheduler.start(); // 定义一个Job 绑定到 HelloJob.class
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build(); // 定义一个触发器,每 10s 执行一次任务
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInSeconds(10))
.build(); // 调度器调度任务
Date date = scheduler.scheduleJob(job, trigger);
LOGGER.info("Quartz 调度器启动时间:{}",date);
// 调用shutdown()方法关闭调度器,否则任务一直在运行
// scheduler.shutdown(); } catch (SchedulerException e) {
e.printStackTrace();
}
}
}

Daily Time 触发器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.DailyTimeIntervalScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TimeOfDay;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Quartz daily time 触发器示例
*
* @author lihw
* @date 2021-12-27 17:48:011
*/
public class QuartzScheduleDailyTimeTriggerDemo { private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleDailyTimeTriggerDemo.class); public static void main(String[] args) {
try {
// 从工厂类获取调度器示例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动调度器
scheduler.start(); // 定义一个Job 绑定到 HelloJob.class
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build(); // 定义一个触发器,每 10s 执行一次任务,到 11点27分停止触发
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withIntervalInSeconds(10)
.endingDailyAt(TimeOfDay.hourAndMinuteOfDay(11, 27)))
.build();
// 调度器调度任务
Date date = scheduler.scheduleJob(job, trigger);
LOGGER.info("Quartz 调度器启动时间:{}", date);
// 调用shutdown()方法关闭调度器,否则任务一直在运行
// scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

JDBC JobStore

上边的示例都是存储在内存中,这里展示了如何存储在数据库中.

1. 执行建表语句

数据库初始化脚本在quartz-2.3.0.jar的/org/quartz/impl/jdbcjobstore/包下.我这里使用的是mysql 数据库,选择tables_mysql_innodb.sql 脚本执行.脚本内容如下:


DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS; CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(190) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(190) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB; CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(190) NULL,
JOB_GROUP VARCHAR(190) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB; CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB; CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB; CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP); CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); commit;

2.引入 mysql 驱动包

     <!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>

3.配置 quartz-jdbc.properties

## Quartz 配置信息

# 调度器名字
org.quartz.scheduler.instanceName = black-schedule
# 线程池大小
org.quartz.threadPool.threadCount = 3
# ====================================================================================== #
# 任务存储方式选择 JDBC存储(对应sql在 org.quartz.impl.jdbcjobstore.Constants 常量类中)
# JDBC 存储有两个实现 JobStoreCMT 和 JobStoreXT ,其中:
# JobStoreCMT:使用JTA容器管理事务,自己并不处理事务提交和回滚
# JobStoreTX: 通过 JDBC 自己管理事务提交和回滚,适合单体应用.
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
# 数据库驱动委派类(必须配置)
# org.quartz.impl.jdbcjobstore.StdJDBCDelegate (for fully JDBC-compliant drivers)
# org.quartz.impl.jdbcjobstore.MSSQLDelegate (for Microsoft SQL Server, and Sybase)
# org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
# org.quartz.impl.jdbcjobstore.WebLogicDelegate (for WebLogic drivers)
# org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
# org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate (for Oracle drivers used within Weblogic)
# org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate (for Oracle drivers used within Weblogic)
# org.quartz.impl.jdbcjobstore.CloudscapeDelegate
# org.quartz.impl.jdbcjobstore.DB2v6Delegate
# org.quartz.impl.jdbcjobstore.DB2v7Delegate
# org.quartz.impl.jdbcjobstore.DB2v8Delegate
# org.quartz.impl.jdbcjobstore.HSQLDBDelegate
# org.quartz.impl.jdbcjobstore.PointbaseDelegate
# org.quartz.impl.jdbcjobstore.SybaseDelegate
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 数据源配置(必须配置) blackQuartz 是数据源名字
org.quartz.jobStore.dataSource = blackQuartz
# Quartz 表前缀
org.quartz.jobStore.tablePrefix=QRTZ_
# 指示 JobDataMaps 中的所有数据都是 String 类型,这样不用序列化存储到 BLOB 列中
org.quartz.jobStore.useProperties=false
# 多长时间认定 触发器错过了下次触发时间,默认 60000 毫秒
org.quartz.jobStore.misfireThreshold=60000
# 开启集群特性
org.quartz.jobStore.isClustered=false
# 集群检查频率间隔,默认15000毫秒
org.quartz.jobStore.clusterCheckinInterval=15000
# 一次性处理未触发的触发器最大数量,默认 20
org.quartz.jobStore.maxMisfiresToHandleAtATime=20
# 不允许 setAutoCommit(false) true-不允许,false-允许
org.quartz.jobStore.dontSetAutoCommitFalse=false
# 加锁查询 LOCKS 表的一行数据,{0}是表前缀(tablePrefix),{1}是调度器名字
org.quartz.jobStore.selectWithLockSQL="SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE"
# 设置事务隔离级别为串行 true-设置,false-不设置
org.quartz.jobStore.txIsolationLevelSerializable=false
# 如果 org.quartz.scheduler.batchTriggerAcquisitionMaxCount >1 那么此属性必须设置为 true
org.quartz.jobStore.acquireTriggersWithinLock=false
# 锁处理类,用于生产 Semaphore 实例在 job store data 上进行锁控制
#org.quartz.jobStore.lockHandler.class=null # 管道分隔的属性集合 在初始化阶段传给DriverDelegate使用,格式:"settingName=settingValue|otherSettingName=otherSettingValue|..."
#org.quartz.jobStore.driverDelegateInitString=
# ====================================================================================== # # ====================================================================================== #
# 数据源名字为blackQuartz的 数据源配置(数据库初始化脚本在quartz-2.3.0.jar的/org/quartz/impl/jdbcjobstore/包下)
# ====================================================================================== #
org.quartz.dataSource.blackQuartz.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.blackQuartz.URL = jdbc:mysql://localhost:3306/black?characterEncoding=UTF8&connectTimeout=6000&socketTimeout=6000&connectionTimeZone=Asia/Shanghai
org.quartz.dataSource.blackQuartz.user = black
org.quartz.dataSource.blackQuartz.password = Black@123
org.quartz.dataSource.blackQuartz.maxConnections = 5
org.quartz.dataSource.blackQuartz.validationQuery=select 0

4.编写测试类

package org.black.demo.quartz;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date; import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class HelloJob implements Job{ private static final Logger LOGGER = LoggerFactory.getLogger(HelloJob.class); @Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOGGER.info("任务明细:{}", context.getJobDetail());
LOGGER.info("激活的实例ID{}",context.getFireInstanceId());
Date d =context.getFireTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOGGER.info("调度器:{}",context.getScheduler());
LOGGER.info("调度器激活时间:{}",f.format(context.getScheduledFireTime()));
if(context.getPreviousFireTime() != null) {
LOGGER.info("上次调用时间:{}",f.format(context.getPreviousFireTime()));
}
LOGGER.info("下次调用时间:{}",f.format(context.getNextFireTime()));
LOGGER.info("触发器:{}",context.getTrigger());
LOGGER.info("触发时间:{}", f.format(d));
LOGGER.info("job 实例:{}", context.getJobInstance());
LOGGER.info("job 运行时长:{}s", context.getJobRunTime());
LOGGER.info("Job 设置的返回结果:{}",context.getResult());
LOGGER.info("MergedJobDataMap:{}", context.getMergedJobDataMap());
//
// LOGGER.info("恢复任务时对应的触发器key:{}",context.getRecoveringTriggerKey());
LOGGER.info("重复激活次数:{}",context.getRefireCount()); LocalDateTime date = LocalDateTime.now();
String curDateTime = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LOGGER.info("时间:{},当前线程:{} - 执行 HelloJob 任务",curDateTime,Thread.currentThread().getName() );
}
}
package org.black.demo.quartz;

import java.util.Date;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Quartz 示例
*
* @author lihw
* @date 2021-12-27 17:48:011
*/
public class QuartzScheduleJDBCDemo { private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleJDBCDemo.class); public static void main(String[] args) {
try {
// 从工厂类获取调度器示例
StdSchedulerFactory factory = new StdSchedulerFactory();
// 指定加载quartz-jdbc.properties配置
factory.initialize("quartz-jdbc.properties");
Scheduler scheduler = factory.getScheduler();
// 启动调度器
scheduler.start(); // 定义一个Job 绑定到 HelloJob.class
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build(); // 定义一个触发器,每 4s 执行一次任务
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever())
.build(); // 调度器调度任务
Date date = scheduler.scheduleJob(job, trigger);
LOGGER.info("Quartz 调度器启动时间:{}",date);
// 调用shutdown()方法关闭调度器,否则任务一直在运行
// scheduler.shutdown(); } catch (SchedulerException e) {
e.printStackTrace();
}
}
}

5. 测试

控制台输出:

[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:46:05,当前线程:black-schedule_Worker-1 - 执行 HelloJob 任务
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 任务明细:JobDetail 'group1.job1': jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 激活的实例IDNON_CLUSTERED1640663163286
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 调度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 调度器激活时间:2021-12-28 11:46:09
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 上次调用时间:2021-12-28 11:46:05
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 下次调用时间:2021-12-28 11:46:13
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 触发器:Trigger 'group1.trigger1': triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:13 CST 2021
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 触发时间:2021-12-28 11:46:09
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 实例:org.black.demo.quartz.HelloJob@f8b8a7d
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 运行时长:-1s
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - Job 设置的返回结果:null
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 重复激活次数:0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:46:09,当前线程:black-schedule_Worker-2 - 执行 HelloJob 任务
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 任务明细:JobDetail 'group1.job1': jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 激活的实例IDNON_CLUSTERED1640663163287
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 调度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 调度器激活时间:2021-12-28 11:46:13
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 上次调用时间:2021-12-28 11:46:09
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 下次调用时间:2021-12-28 11:46:17
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 触发器:Trigger 'group1.trigger1': triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:17 CST 2021
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 触发时间:2021-12-28 11:46:13
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - job 实例:org.black.demo.quartz.HelloJob@7a800c47
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - job 运行时长:-1s
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - Job 设置的返回结果:null
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 重复激活次数:0
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:46:13,当前线程:black-schedule_Worker-3 - 执行 HelloJob 任务
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 任务明细:JobDetail 'group1.job1': jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 激活的实例IDNON_CLUSTERED1640663163288
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 调度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 调度器激活时间:2021-12-28 11:46:17
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 上次调用时间:2021-12-28 11:46:13
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 下次调用时间:2021-12-28 11:46:21
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 触发器:Trigger 'group1.trigger1': triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:21 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 触发时间:2021-12-28 11:46:17
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 实例:org.black.demo.quartz.HelloJob@1053e9f7
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 运行时长:-1s
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - Job 设置的返回结果:null
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 重复激活次数:0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 时间:2021-12-28 11:46:17,当前线程:black-schedule_Worker-1 - 执行 HelloJob 任务

执行以下sql查询 表数据:

select * from QRTZ_JOB_DETAILS;
select * from QRTZ_FIRED_TRIGGERS;
select * from QRTZ_PAUSED_TRIGGER_GRPS;
select * from QRTZ_SCHEDULER_STATE;
select * from QRTZ_LOCKS;
select * from QRTZ_SIMPLE_TRIGGERS;
select * from QRTZ_SIMPROP_TRIGGERS;
select * from QRTZ_CRON_TRIGGERS;
select * from QRTZ_BLOB_TRIGGERS;
select * from QRTZ_TRIGGERS;
select * from QRTZ_JOB_DETAILS;
select * from QRTZ_CALENDARS;

SpringBoot 集成

待续...

Quartz 使用记录的更多相关文章

  1. Quartz 学习记录1

    原因 公司有一些批量定时任务可能需要在夜间执行,用的是quartz和spring batch两个框架.quartz是个定时任务框架,spring batch是个批处理框架. 虽然我自己的小玩意儿平时不 ...

  2. quartz 实例记录

    之前介绍过了quartz的一些相关理论知识,感觉上挺简单的,实际动手操作也确实如此,去quartz的官网上把Jar包下载下来以后,会看到它的目录里有例子程序,看完第一个例子觉得还可以,但是看后面两个例 ...

  3. quartz相关记录

    1.http://www.quartz-scheduler.org/api/2.3.1-SNAPSHOT/ api地址 2.https://www.jianshu.com/p/3c3e166a7da1 ...

  4. Quartz使用记录总结

    Quartz是一个任务调度框架,最近在项目中有用到,所以做个记录总结. 一.主要元素 Scheduler:调度器,控制任务的调度,将JobDetail和Trigger注册到Scheduler加以控制. ...

  5. quartz问题记录-missed their scheduled fire-time

    这里有3个原因:1.所有的woker thread(工作线程; 辅助线程)都在运行其他的job2.scheduler(调度器)down了(关于这个down.我不太明确是shutdown了..还是挂掉了 ...

  6. Quartz学习记录

    参考资料: 官方网站 Quartz使用总结

  7. Quartz任务调度 服务日志+log4net打印日志+制作windows服务

    引言 现在许多的项目都需要定时的服务进行支撑,而我们经常用到的定时服务就是Quartz任务调度了.不过我们在使用定时Job进行获取的时候,有时候我们就需要记录一下自定义的日志,甚至我们还会对执行定时J ...

  8. Quartz SpringBoot 简单整合一下

    一次简单的代码整合记录. 数据库准备 如果是MySQL可能出现一些小问题.比如联合主键长度超限制,已经记录解决办法了. CREATE TABLE QRTZ_JOB_DETAILS ( SCHED_NA ...

  9. Quartz.net使用记录

    1.引入dll文件: nuget控制台:安装quartz:Install-Package Quartz 安装log4net:Install-Package log4net,这里使用log4net记录一 ...

随机推荐

  1. CF258D题解

    太厉害啦 首先做期望题最不能忘记的就是期望的线性性. 所以我们直接将全局逆序对对数拆成两个数其中一个比另一个大的期望(概率),设为 \(f[i][j]\),初值为 \([a_i>b_j]\). ...

  2. spring——通过xml文件配置IOC容器

    创建相关的类(这里是直接在之前类的基础上进行修改) package com.guan.dao; public interface Fruit { String getFruit(); } packag ...

  3. Fiddler修改接口下行数据,mock测试

    应用场景:在不修改服务器代码的情况下,临时改变接口下行数据值,便于查看界面效果.. 使用工具:Fiddler 使用方法:连接Fiddler,使用代理. Fiddler配置方法如下: 1.定位到Fidd ...

  4. json知识点总结(一)--基础介绍

    前言 JSON是一种轻量化的数据编码方式它不依赖于编程语言是独立的文本格式.和xml相比JSON具有格式简洁,转译速度快的特点,因此现在被广泛使用.JSON的本质是字符串,采用了特定的分隔方式对字符串 ...

  5. 手把手带你使用EFR32 -- 土壤湿度传感器变身第二形态,以 ZigBee 形态出击

    前言 后悔,总之就是非常后悔,我当时到底是为啥才会猪油蒙心,选择了 EFR32 来学习 ZigBee 使用啊? EFR32 这玩意看性能确实不错,但是资料太少了,EmberZnet SDK 也是用得一 ...

  6. Git常见错误整理

    参考文章 git 排错 fatal: 'git status --porcelain' failed in submodule abi/cpp 1 fatal: 'git status --porce ...

  7. 🍛 餐厅吃饭版理解 IO 模型:阻塞 / 非阻塞 / IO 复用 / 信号驱动 / 异步

    IO 概念 一个基本的 IO,它会涉及到两个系统对象,一个是调用这个 IO 的进程对象,另一个就是系统内核 (kernel).当一个 read 操作发生时,它会经历两个阶段: 通过 read 系统调用 ...

  8. Oracle数据常用的备份与恢复?

    Oracle的备份与恢复有三种标准的模式,大致分为两大类,备份恢复(物理上的)以及导入导出(逻辑上的),而备份恢复又可以根据数据库的工作模式分为非归档模式(Nonarchivelog-style)和归 ...

  9. Chroot 特性 ?

    3.2.0 版本后,添加了 Chroot 特性,该特性允许每个客户端为自己设置一个命名 空间.如果一个客户端设置了 Chroot,那么该客户端对服务器的任何操作,都将 会被限制在其自己的命名空间下. ...

  10. Mybatis的XML文件调用静态方法

    如果需要在Mapper文件中调用静态方法,需要 <choose> // 需要静态方法返回true还是false <when test="@staticClass@stati ...