【使用篇二】Quartz自动化配置集成(17)
出处:https://www.jianshu.com/p/49133c107143
定时任务在企业项目比较常用到,几乎所有的项目都会牵扯该功能模块,定时任务一般会处理指定时间点执行某一些业务逻辑、间隔时间执行某一些业务逻辑等。
在新版本的SpringBoot2.0发布后,针对Quartz新版本进行了 AutoConfiguration自动化配置,省去了很多繁琐的配置。
本章节我们将详细讲解如何使用外置的Quartz以及SpringBoot的Quartz自动化配置。
这里采用的是Quartz2.3.0版本,针对该版本,这里列出oracle与mysql的建表语句:
1. oracle
-- 存储每一个已配置的 Job 的详细信息
CREATE TABLE qrtz_job_details
(
SCHED_NAME VARCHAR2(120) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
JOB_CLASS_NAME VARCHAR2(250) NOT NULL,
IS_DURABLE VARCHAR2(1) NOT NULL,
IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
-- 存储已配置的 Trigger 的信息
CREATE TABLE qrtz_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
NEXT_FIRE_TIME NUMBER(13) NULL,
PREV_FIRE_TIME NUMBER(13) NULL,
PRIORITY NUMBER(13) NULL,
TRIGGER_STATE VARCHAR2(16) NOT NULL,
TRIGGER_TYPE VARCHAR2(8) NOT NULL,
START_TIME NUMBER(13) NOT NULL,
END_TIME NUMBER(13) NULL,
CALENDAR_NAME VARCHAR2(200) NULL,
MISFIRE_INSTR NUMBER(2) NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
-- 存储简单的 Trigger,包括重复次数,间隔,以及已触的次数
CREATE TABLE qrtz_simple_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
REPEAT_COUNT NUMBER(7) NOT NULL,
REPEAT_INTERVAL NUMBER(12) NOT NULL,
TIMES_TRIGGERED NUMBER(10) NOT NULL,
CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
-- 存储 Cron Trigger,包括 Cron 表达式和时区信息
CREATE TABLE qrtz_cron_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CRON_EXPRESSION VARCHAR2(120) NOT NULL,
TIME_ZONE_ID VARCHAR2(80),
CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_simprop_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
STR_PROP_1 VARCHAR2(512) NULL,
STR_PROP_2 VARCHAR2(512) NULL,
STR_PROP_3 VARCHAR2(512) NULL,
INT_PROP_1 NUMBER(10) NULL,
INT_PROP_2 NUMBER(10) NULL,
LONG_PROP_1 NUMBER(13) NULL,
LONG_PROP_2 NUMBER(13) NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR2(1) NULL,
BOOL_PROP_2 VARCHAR2(1) NULL,
CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
-- Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,<span style="color:#800080;">JobStore</span> 并不知道如何存储实例的时候)
CREATE TABLE qrtz_blob_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
BLOB_DATA BLOB NULL,
CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
-- 以 Blob 类型存储 Quartz 的 Calendar 信息
CREATE TABLE qrtz_calendars
(
SCHED_NAME VARCHAR2(120) NOT NULL,
CALENDAR_NAME VARCHAR2(200) NOT NULL,
CALENDAR BLOB NOT NULL,
CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
-- 存储已暂停的 Trigger 组的信息
CREATE TABLE qrtz_paused_trigger_grps
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
-- 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息
CREATE TABLE qrtz_fired_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
ENTRY_ID VARCHAR2(95) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
FIRED_TIME NUMBER(13) NOT NULL,
SCHED_TIME NUMBER(13) NOT NULL,
PRIORITY NUMBER(13) NOT NULL,
STATE VARCHAR2(16) NOT NULL,
JOB_NAME VARCHAR2(200) NULL,
JOB_GROUP VARCHAR2(200) NULL,
IS_NONCONCURRENT VARCHAR2(1) NULL,
REQUESTS_RECOVERY VARCHAR2(1) NULL,
CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
-- 存储少量的有关 Scheduler 的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
CREATE TABLE qrtz_scheduler_state
(
SCHED_NAME VARCHAR2(120) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
LAST_CHECKIN_TIME NUMBER(13) NOT NULL,
CHECKIN_INTERVAL NUMBER(13) NOT NULL,
CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
-- 存储程序的悲观锁的信息(假如使用了悲观锁)
CREATE TABLE qrtz_locks
(
SCHED_NAME VARCHAR2(120) NOT NULL,
LOCK_NAME VARCHAR2(40) NOT NULL,
CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
); 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);
2. mysql
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(200) NOT NULL,
JOB_GROUP VARCHAR(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) 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(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(200) 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(200) 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(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) 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(200) NULL,
JOB_GROUP VARCHAR(200) 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(200) 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);
一、分布式单节点持久化
采用jobDetail使用Spring Ioc托管方式来完成整合。
(一)基本配置
1. 引入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid.version>1.1.5</druid.version>
<quartz.version>2.3.0</quartz.version>
</properties> <dependencies> <!--web相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--数据库相关依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--quartz相关依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>${quartz.version}</version>
</dependency>
<!--定时任务需要依赖context模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. application.yml
server:
port: 8082 #数据源
spring:
datasource:
url: jdbc:mysql://192.168.178.5:12345/cloudDB01?useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
3. QuartzConfiguration
@Configuration
@EnableScheduling //开启任务调度
public class QuartzConfiguration { /**
* 继承org.springframework.scheduling.quartz.SpringBeanJobFactory
* 实现任务实例化方式
*/
public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware { private transient AutowireCapableBeanFactory beanFactory; @Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
} /**
* 将job实例交给spring ioc托管
* 我们在job实例实现类内可以直接使用spring注入的调用被spring ioc管理的实例
* @param bundle
* @return
* @throws Exception
*/
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
/**
* 将job实例交付给spring ioc
*/
beanFactory.autowireBean(job);
return job;
}
} /**
* 配置任务工厂实例
* @param applicationContext spring上下文实例
* @return
*/
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext)
{
/**
* 采用自定义任务工厂 整合spring实例来完成构建任务
* see {@link AutowiringSpringBeanJobFactory}
*/
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
} /**
* 配置任务调度器
* 使用项目数据源作为quartz数据源
* @param jobFactory 自定义配置任务工厂
* @return
* @throws Exception
*/
@Bean(destroyMethod = "destroy")
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws Exception
{
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
//将spring管理job自定义工厂交由调度器维护
schedulerFactoryBean.setJobFactory(jobFactory);
//设置覆盖已存在的任务
schedulerFactoryBean.setOverwriteExistingJobs(true);
//项目启动完成后,等待2秒后开始执行调度器初始化
schedulerFactoryBean.setStartupDelay(2);
//设置调度器自动运行
schedulerFactoryBean.setAutoStartup(true);
//设置数据源,使用与项目统一数据源
schedulerFactoryBean.setDataSource(dataSource);
//设置上下文spring bean name
schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");
//设置配置文件位置
schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
return schedulerFactoryBean;
}
}
(1) SchedulerFactoryBean
官方quartz有两种持久化的配置方案。
第一种:采用quartz.properties配置文件配置独立的定时任务数据源,可以与使用项目的数据库完全独立。
第二种:采用与创建项目统一个数据源,定时任务持久化相关的表与业务逻辑在同一个数据库内。
本章节我们采用的是第二种方案。
上面创建SchedulerFactoryBean的参数中有一个是DataSource,DataSource会根据application.yml文件内的数据源相关配置自动实例化DataSource实例。
通过调用SchedulerFactoryBean对象的setConfigLocation方法来设置quartz定时任务框架的基本配置,配置文件所在位置:resources/quartz.properties => classpath:/quartz.properties下。
注意:quartz.properties配置文件一定要放在classpath下,放在别的位置有部分功能不会生效。
4. quartz.properties文件的配置
#调度器实例名称
org.quartz.scheduler.instanceName = quartzScheduler #调度器实例编号自动生成
org.quartz.scheduler.instanceId = AUTO #持久化方式配置
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX #持久化方式配置数据驱动,MySQL数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate #quartz相关数据表前缀名
org.quartz.jobStore.tablePrefix = QRTZ_ #开启分布式部署
org.quartz.jobStore.isClustered = true
#配置是否使用
org.quartz.jobStore.useProperties = false #分布式节点有效性检查时间间隔,单位:毫秒
org.quartz.jobStore.clusterCheckinInterval = 20000 #线程池实现类
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool #执行最大并发线程数量
org.quartz.threadPool.threadCount = 10 #线程优先级
org.quartz.threadPool.threadPriority = 5 #配置为守护线程,设置后任务将不会执行
#org.quartz.threadPool.makeThreadsDaemons=true #配置是否启动自动加载数据库内的定时任务,默认true
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
在上面配置中org.quartz.jobStore.class与org.quartz.jobStore.driverDelegateClass是定时任务持久化的关键配置,配置了数据库持久化定时任务以及采用MySQL数据库进行连接,当然这里我们也可以配置其他的数据库,如下所示:
PostgreSQL : org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
Sybase : org.quartz.impl.jdbcjobstore.SybaseDelegate
MSSQL : org.quartz.impl.jdbcjobstore.MSSQLDelegate
HSQLDB : org.quartz.impl.jdbcjobstore.HSQLDBDelegate
Oracle : org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.tablePrefix属性配置了定时任务数据表的前缀,在quartz官方提供的创建表SQL脚本默认就是qrtz_,在对应的XxxDelegate驱动类内也是使用的默认值,所以这里我们如果修改表名前缀,配置可以去掉。
org.quartz.jobStore.isClustered属性配置了开启定时任务分布式功能,再开启分布式时对应属性org.quartz.scheduler.instanceId 改成Auto配置即可,实例唯一标识会自动生成。
(二)测试
1. 创建一个简单的商品数据表
DROP TABLE IF EXISTS `basic_good_info`;
CREATE TABLE `basic_good_info` (
`BGI_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品编号',
`BGI_NAME` varchar(20) DEFAULT NULL COMMENT '商品名称',
`BGI_PRICE` decimal(8,2) DEFAULT NULL COMMENT '单价',
`BGI_UNIT` varchar(10) DEFAULT NULL COMMENT '单位',
PRIMARY KEY (`BGI_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='商品基本信息';
2. 再来添加一个商品添加的控制器方法
@RestController
@RequestMapping(value = "/good")
public class GoodController
{
/**
* 商品业务逻辑实现
*/
@Autowired
private GoodInfoService goodInfoService;
/**
* 添加商品
* @return
*/
@RequestMapping(value = "/save",method = {RequestMethod.POST})
public Long save(@RequestBody Map good) throws Exception {
return goodInfoService.saveGood(good);
}
}
在请求商品添加方法时,我们调用了GoodInfoService内的saveGood方法。
@Service
@Transactional(rollbackFor = Exception.class)
public class GoodInfoService {
/**
* 注入任务调度器
*/
@Autowired
private Scheduler quartzScheduler; @Autowired
private JdbcTemplate jdbcTemplate; /**
* 保存商品基本信息
* @param good 商品实例
* @return
*/
public Long saveGood(Map good) throws Exception {
String bgiName = String.valueOf(good.get("name"));
Double bgiPrice = Double.parseDouble(String.valueOf(good.get("price")));
String sql = "insert into basic_good_info(BGI_NAME, BGI_PRICE) values('" + bgiName + "', " + bgiPrice + ")";
Connection conn = jdbcTemplate.getDataSource().getConnection();
PreparedStatement psmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
psmt.executeUpdate();
ResultSet keyResultSet = psmt.getGeneratedKeys();
keyResultSet.next();
long num =keyResultSet.getLong(1);
System.out.println(num);
//构建创建商品定时任务
buildCreateGoodTimer();
//构建商品库存定时任务
buildGoodStockTimer();
return num;
}
}
这个只是作为保存商品的操作,后面我们会模拟一个请求,在商品添加完成后1分钟我们通知后续的逻辑进行下一步处理,同时开始商品库存定时检查的任务。
3. 定义商品添加定时任务
创建一个任务实例,并且继承org.springframework.scheduling.quartz.QuartzJobBean抽象类,重写父抽象类内的executeInternal方法来实现任务的主体逻辑。
public class GoodAddTimer extends QuartzJobBean {
/**
* logback
*/
static Logger logger = LoggerFactory.getLogger(GoodAddTimer.class); /**
* 定时任务逻辑实现方法
* 每当触发器触发时会执行该方法逻辑
*
* @param jobExecutionContext 任务执行上下文
* @throws JobExecutionException
*/
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("商品添加完成后执行任务,任务时间:{}", new Date());
}
}
4. 定义商品库存检查任务
继承org.springframework.scheduling.quartz.QuartzJobBean抽象类实现抽象类内的executeInternal方法。
public class GoodStockCheckTimer extends QuartzJobBean{
/**
* logback
*/
static Logger logger = LoggerFactory.getLogger(GoodStockCheckTimer.class); @Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("执行库存检查定时任务,执行时间:{}",new Date());
}
}
5. 分别将两个任务添加到调度器
在GoodInfoService类内添加buildCreateGoodTimer方法用于实例化商品添加任务:
/**
* 构建创建商品定时任务
*/
public void buildCreateGoodTimer() throws Exception {
//设置开始时间为1分钟后
long startAtTime = System.currentTimeMillis() + 1000 * 60;
//任务名称
String name = UUID.randomUUID().toString();
//任务所属分组
String group = GoodAddTimer.class.getName();
//创建任务
JobDetail jobDetail = JobBuilder.newJob(GoodAddTimer.class).withIdentity(name,group).build();
//创建任务触发器
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(name,group).startAt(new Date(startAtTime)).build();
//将触发器与任务绑定到调度器内
quartzScheduler.scheduleJob(jobDetail, trigger);
}
在上面方法中我们定义的GoodAddTimer
实例只运行一次,在商品添加完成后延迟1分钟进行调用任务主体逻辑。
在GoodInfoService类内添加buildGoodStockTimer方法用于实例化商品库存检查任务:
public void buildGoodStockTimer() throws Exception {
//任务名称
String name = UUID.randomUUID().toString();
//任务所属分组
String group = GoodStockCheckTimer.class.getName(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/30 * * * * ?");
//创建任务
JobDetail jobDetail = JobBuilder.newJob(GoodStockCheckTimer.class).withIdentity(name,group).build();
//创建任务触发器
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(name,group).withSchedule(scheduleBuilder).build();
//将触发器与任务绑定到调度器内
quartzScheduler.scheduleJob(jobDetail, trigger);
}
该任务的触发器我们采用了cron
表达式来设置,每隔30秒执行一次任务主体逻辑。
注:任务的名称以及任务的分组是为了区分任务做的限制,在同一个分组下如果加入同样名称的任务,则会提示任务已经存在,添加失败的提示。
6. 单元测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {QuartzApplication.class})
public class QuartzApplicationTests {
/**
* 模拟mvc测试对象
*/
private MockMvc mockMvc; /**
* web项目上下文
*/
@Autowired
private WebApplicationContext webApplicationContext; /**
* 所有测试方法执行之前执行该方法
*/
@Before
public void before() {
//获取mockmvc对象实例
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
} /**
* 测试添加商品
*
* @throws Exception
*/
@Test
public void addGood() throws Exception {
Map params = new HashMap();
params.put("name", "西瓜");
params.put("unit","斤");
params.put("price", "12.88");
String requestJson = JSONObject.toJSONString(params);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/good/save")
.contentType(MediaType.APPLICATION_JSON).content(requestJson))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().is(200))
.andReturn();
result.getResponse().setCharacterEncoding("UTF-8");
System.out.println(result.getResponse().getContentAsString());
}
}
执行后,看看QRTZ_CRON_TRIGGERS、QRTZ_FIRED_TRIGGERS、QRTZ_JOB_DETAILS、QRTZ_LOCKS等表是否有数据。
二、分布式多节点负载持久化
这里要特别注意任务在持久化到数据库内时会保存任务的全路径,quartz在运行任务时会根据任务全路径去执行,如果不一致则会提示找不到指定类,所以多节点中各个节点的任务路径要一致。
1. 配置分布式
在单节点持久化中,其实已经为分布式做好了相关配置。
(1) org.quartz.scheduler.instanceId : 定时任务的实例编号,如果手动指定需要保证每个节点的唯一性,因为quartz不允许出现两个相同instanceId的节点,我们这里指定为Auto就可以了,我们把生成编号的任务交给quartz。
(2) org.quartz.jobStore.isClustered: 这个属性才是真正的开启了定时任务的分布式配置,当我们配置为true时quartz框架就会调用ClusterManager来初始化分布式节点。
(3) org.quartz.jobStore.clusterCheckinInterval:配置了分布式节点的检查时间间隔,单位:毫秒。
完整的quartz.properties文件:
#调度器实例名称
org.quartz.scheduler.instanceName = quartzScheduler #调度器实例编号自动生成
org.quartz.scheduler.instanceId = AUTO #持久化方式配置
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX #持久化方式配置数据驱动,MySQL数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate #quartz相关数据表前缀名
org.quartz.jobStore.tablePrefix = QRTZ_ #开启分布式部署
org.quartz.jobStore.isClustered = true
#配置是否使用
org.quartz.jobStore.useProperties = false #分布式节点有效性检查时间间隔,单位:毫秒
org.quartz.jobStore.clusterCheckinInterval = 10000 #线程池实现类
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool #执行最大并发线程数量
org.quartz.threadPool.threadCount = 10 #线程优先级
org.quartz.threadPool.threadPriority = 5 #配置为守护线程,设置后任务将不会执行
#org.quartz.threadPool.makeThreadsDaemons=true #配置是否启动自动加载数据库内的定时任务,默认true
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
当我们启动任务节点时,会根据org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread属性配置进行是否自动加载任务,默认true自动加载数据库内的任务到节点。
按照上面单节点quartz-first,新建一个叫做quartz-second的节点,这样就有两个节点了。两个节点需要做以下修改:
- quartz-second修改application.yml的端口,使其与quartz-first不同
- quartz-first和quartz-second修改任务的输出日志,添加一些代表各自节点的输出日志,如添加quartz-first或quartz-second的日志
启动quartz-first和quartz-second项目,在控制台日志中可以看出类似以下的日志,那是自动分配的实例id:
Scheduler quartzScheduler_$_SKY-20190903YUM1573950650675 started.
我们发现如果两个节点同时启动,哪个节点先把节点信息注册到数据库就获得了优先执行权,另外一个节点不会执行,相当于是备份的。当这个正在执行的节点宕掉了,这个节点就会接收调度任务。这就是quartz与schedule的一个很大区别,它已经实现了分布式的任务调度了,不会有多个节点重复执行任务的情况。
2. 传递参数到任务
我们平时在使用任务时,如果是针对性比较强的业务逻辑,肯定需要特定的参数来完成业务逻辑的实现。这个就要使用JobDataMap来实现了。
//1. 通过JobDetail获取一个JobDataMap,并往其中添加我们要传递的参数
jobDetail.getJobDataMap().put("goodId",goodId); //2. 在任务调度的主方法executeInternal(JobExecutionContext jobExecutionContext)会传入JobExecutionContext 上下文,我们可以通过这个获取传递的参数值
JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap();
Long goodId = dataMap.getLong("goodId");
三、SpringBoot的Quartz配置自动化
在SpringBoot2.0后,针对Quartz进行了 AutoConfiguration自动化配置,省去了很多繁琐的配置。
此操作都是在上面的项目基础上做改造。
1. 修改pom.xml依赖
<!--quartz相关依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>${quartz.version}</version>
</dependency>
>>>>替换为:>>>>
<!--quartz依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2. 删除QuartzConfiguration配置类
之前我们使用QuartzConfiguration配置类来完成了Quartz需要的一系列配置,如:JobFactory、SchedulerFactoryBean等,在我们添加spring-boot-starter-quartz依赖后就不需要主动声明工厂类,因为spring-boot-starter-quartz已经为我们自动化配置好了。
3.自动化源码
我们找到spring-boot-autoconfigure-x.x.x.RELEASE.jar,找到org.springframework.boot.autoconfigure.quartz,该目录就是SpringBoot为我们提供的Quartz自动化配置源码实现,在该目录下有如下所示几个类:
- AutowireCapableBeanJobFactory
该类替代了我们之前在QuartzConfiguration配置类的AutowiringSpringBeanJobFactory内部类实现,主要作用是我们自定义的QuartzJobBean子类被Spring IOC进行托管,可以在定时任务类内使用注入任意被Spring IOC托管的类。
- JobStoreType
该类是一个枚举类型,定义了对应application.yml、application.properties文件内spring.quartz.job-store-type配置,其目的是配置quartz任务的数据存储方式,分别为:MEMORY(内存方式:默认)、JDBC(数据库方式)。
- QuartzAutoConfiguration
该类是自动配置的主类,内部配置了SchedulerFactoryBean以及JdbcStoreTypeConfiguration,使用QuartzProperties作为属性自动化配置条件。
- QuartzDataSourceInitializer
该类主要用于数据源初始化后的一些操作,根据不同平台类型的数据库进行选择不同的数据库脚本。
- QuartzProperties
该类对应了spring.quartz在application.yml、application.properties文件内开头的相关配置。
- SchedulerFactoryBeanCustomizer
这是一个接口,我们实现该接口后并且将实现类使用Spring IOC托管,可以完成SchedulerFactoryBean的个性化设置,这里的设置完全可以对SchedulerFactoryBean做出全部的设置变更。
4.spring.quartz配置
application.yml配置:
spring:
quartz:
#相关属性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
#数据库方式
job-store-type: jdbc
#初始化表结构
#jdbc:
#initialize-schema: never
上面的spring.quartz.properties:
该配置其实代替了之前的quartz.properties,我们把之前quartz.properties配置文件内的所有配置转换成YAML风格,对应的添加在该配置下即可,在QuartzAutoConfiguration类内,会自动调用SchedulerFactoryBean的setQuartzProperties方法,把spring.quartz.properties内的所有配置进行设置。
@Bean
@ConditionalOnMissingBean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(new AutowireCapableBeanJobFactory(this.applicationContext.getAutowireCapableBeanFactory()));
// 如果配置了spring.quartz.properties
if (!this.properties.getProperties().isEmpty()) {
// 将所有properties设置到QuartzProperties
schedulerFactoryBean.setQuartzProperties(this.asProperties(this.properties.getProperties()));
}
......省略部分代码
spring.quartz.job-store-type:设置quartz任务的数据持久化方式,默认是内存方式,我们这里沿用之前的方式,配置JDBC以使用数据库方式持久化任务。
【使用篇二】Quartz自动化配置集成(17)的更多相关文章
- 漫谈:从APP崩溃率标准,到Monkey介绍拓展Maxim,及Jenkins自动化配置,持续集成获取崩溃monkey日志
漫谈:从APP崩溃率标准,到Monkey介绍拓展Maxim,及Jenkins自动化配置,持续集成获取崩溃日志 1.APP崩溃率标准 开发或测试app的同学,对于app崩溃肯定非常熟悉,频繁的线上崩溃属 ...
- SpringBoot系列之集成logback实现日志打印(篇二)
SpringBoot系列之集成logback实现日志打印(篇二) 基于上篇博客SpringBoot系列之集成logback实现日志打印(篇一)之后,再写一篇博客进行补充 logback是一款开源的日志 ...
- Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置
该篇为Sping Boot入门到实战系列入门篇的第四篇.介绍Spring Boot自动化配置的基本原理与实现. Spring Boot之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...
- spring boot1.0 集成quartz 动态配置定时任务
转载自 https://www.imooc.com/article/36278 一.Quartz简介了解 Quartz Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应 ...
- Jmeter(二十八)_Docker+Jmeter+Gitlab+Jenkins+Ant(容器化的接口自动化持续集成平台)
这套接口自动化持续集成环境已经部署差不多了,现在说说我的设计思路 1:利用Docker容器化Gitlab,Jenkins,Jmeter,Ant,链接如下 Docker_容器化gitlab Docker ...
- 源码学习系列之SpringBoot自动配置(篇二)
源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...
- SpringBoot系列之profles配置多环境(篇二)
SpringBoot系列之profles配置多环境(篇二) 继续上篇博客SpringBoot系列之profles配置多环境(篇一)之后,继续写一篇博客进行补充 写Spring项目时,在测试环境是一套数 ...
- SpringBoot自动化配置之二:自动配置(AutoConfigure)原理、EnableAutoConfiguration、condition
自动配置绝对算得上是Spring Boot的最大亮点,完美的展示了CoC约定优于配置: Spring Boot能自动配置Spring各种子项目(Spring MVC, Spring Security, ...
- Spring Boot 探索系列 - 自动化配置篇
26. Logging Prev Part IV. Spring Boot features Next 26. Logging Spring Boot uses Commons Logging f ...
随机推荐
- 200G网盘资源分享
今日偶得大量网盘资源,遂写一博文以分享! 来源:HACK学习呀,微信公众号:HACK学习呀 文件名 链接 提取密码 2015cracer入侵入门到精通视频教程 点我查看 trf3 一笔√带过入侵教程 ...
- Electron开发和Web开发对比
- Elasticsearch系列---初识搜索
概要 本篇主要介绍搜索的报文结构含义.搜索超时时间的处理过程,提及了一下多索引搜索和轻量搜索,最后将精确搜索与全文搜索做了简单的对比. 空搜索 搜索API最简单的形式是不指定索引和类型的空搜索,它将返 ...
- .get的取值特点:.get只起到取值的作用 不能对原值修改
#银行支付接口 def pay_interface(username,cost): user_dic=db_handler.select(username) if user_dic.get('bala ...
- create-react-app 超级慢的解决方法
create-react-app超级慢的解决方法 在操作官方实例Create React App时,需要执行指令: create-react-app my-app 来创建一个新的React应用.由于某 ...
- 深入理解 Spring Cloud 核心组件与底层原理
一.Spring Cloud核心组件:Eureka Netflix Eureka Eureka详解 1.服务提供者 2.服务消费者 3.服务注册中心 二.Spring Cloud核心组件:Ribbon ...
- 集合系列 Map(十三):LinkedHashMap
我们之前说过 LinkedHashMap 是在 HashMap 的基础上,增加了对插入元素的链表维护.那么其到底是怎么实现的呢?今天这篇文章就带我们来一探究竟. public class Linked ...
- REST架构指导方案
目录 REST架构指导方案 何为REST 在WEB系统中应用REST风格 应用约束 对资源应用正确的动词语义 名词性的URI地址 RESTFUL的URL路径实践 单一资源的路径制定 复杂查询的路径制定 ...
- python字符串与字典转换
经常会遇到字典样式字符串的处理,这里做一下记录. load load针对的是文件,即将文件内的json内容转换为dict import json test_json = json.load(open( ...
- Redis 数据淘汰机制
为了更好的利用内存,使Redis存储的都是缓存的热点数据,Redis设计了相应的内存淘汰机制(也叫做缓存淘汰机制) 通过maxmemory 配置项来设置允许用户使用的最大内存大小,当内存数据集大小达到 ...