Spring boot整合quartz定时任
创建工程
创建数据库和表
业务表
CREATE TABLE `basic_good_info` (
`bgi_id` int(11) NOT NULL AUTO_INCREMENT,
`bgi_name` varchar(255) DEFAULT NULL,
`bgi_unit` varchar(255) DEFAULT NULL,
`bgi_price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`bgi_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
quartz脚本
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
#
# By: Ron Cordell - roncordell
# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
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);
commit;
相关配置
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.youfan</groupId>
<artifactId>springbootquartz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springbootquartz</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<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>
<fastjson.version>1.2.40</fastjson.version>
</properties>
<dependencies>
<!--spring data jpa相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--web相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--数据库相关依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
quartz.properties
org.quartz.scheduler.instanceName = schedulerFactoryBean
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
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
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
application.yml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/quartz?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
username: root
password: 888888
jpa:
hibernate:
ddl-auto: update #ddl-auto:设为update表示每次都不会重新建表
show-sql: true
application:
name: quartz-cluster-node-first
server:
port: 8081
#####################################################################################################
# 打印日志
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
com.springms: DEBUG
#####################################################################################################
Quartz配置-QuartzConfiguration
package com.youfan.config;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import javax.sql.DataSource;
/**
* quartz定时任务配置
*/
@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);
beanFactory.autowireBean(job); //将job实例交付给spring ioc
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 自定义配置任务工厂
* @param dataSource 数据源实例
* @return
* @throws Exception
*/
@Bean(destroyMethod = "destroy", autowire = Autowire.NO)
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws Exception {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(jobFactory); // 将spring管理job自定义工厂交由调度器维护
schedulerFactoryBean.setOverwriteExistingJobs(true); // 设置覆盖已存在的任务
schedulerFactoryBean.setStartupDelay(2); // 项目启动完成后,等待2秒后开始执行调度器初始化
schedulerFactoryBean.setAutoStartup(true); // 设置调度器自动运行
schedulerFactoryBean.setDataSource(dataSource); // 设置数据源,使用与项目统一数据源
schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");// 设置上下文spring bean name
schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));// 设置配置文件位置
return schedulerFactoryBean;
}
}
说明:
1)quartz的配置;
对商品的操作
GoodInfoEntity
package com.youfan.goods.entity;
import lombok.Data;
import javax.persistence.*;
import java.math.BigDecimal;
@Entity
@Table(name = "basic_good_info")
@Data
public class GoodInfoEntity {
/**
* 商品编号
*/
@Id
@GeneratedValue
@Column(name = "bgi_id")
private Long id;
/**
* 商品名称
*/
@Column(name = "bgi_name")
private String name;
/**
* 商品单位
*/
@Column(name = "bgi_unit")
private String unit;
/**
* 商品单价
*/
@Column(name = "bgi_price")
private BigDecimal price;
}
说明:
1)商品的实体bean;
GoodInfoRepository
package com.youfan.goods.jpa;
import com.youfan.goods.entity.GoodInfoEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface GoodInfoRepository extends JpaRepository<GoodInfoEntity,Long> {
}
说明:
1)商品数据库的相关操作;
GoodInfoService
package com.youfan.goods.service;
import com.youfan.goods.entity.GoodInfoEntity;
import com.youfan.goods.jpa.GoodInfoRepository;
import com.youfan.timer.GoodAddTimer;
import com.youfan.timer.GoodSecKillRemindTimer;
import com.youfan.timer.GoodStockCheckTimer;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.UUID;
/**
* 商品业务逻辑
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class GoodInfoService {
/**
* 注入任务调度器
*/
@Autowired
private Scheduler scheduler;
/**
* 商品数据接口
*/
@Autowired
private GoodInfoRepository goodInfoRepository;
/**
* 保存商品基本信息
* @param good 商品实例
* @return
*/
public Long saveGood(GoodInfoEntity good) throws Exception {
goodInfoRepository.save(good);
buildCreateGoodTimer(); // 构建创建商品定时任务
buildGoodStockTimer(); // 构建商品库存定时任务
buildGoodSecKillRemindTimer(good.getId()); // 构建商品描述提醒定时任务
return good.getId();
}
/**
* 构建创建商品定时任务
* 执行一次
*/
public void buildCreateGoodTimer() throws Exception {
long startAtTime = System.currentTimeMillis() + 1000 * 60; // 设置开始时间为1分钟后
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();//创建任务触发器
scheduler.scheduleJob(jobDetail, trigger); // 将触发器与任务绑定到调度器内
}
/**
* 构建商品库存定时任务
* 循环执行
* @throws Exception
*/
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();//创建任务触发器
scheduler.scheduleJob(jobDetail, trigger);//将触发器与任务绑定到调度器内
}
/**
* 构建商品秒杀提醒定时任务
* 设置五分钟后执行,传递业务参数
* @throws Exception
*/
public void buildGoodSecKillRemindTimer(Long goodId) throws Exception {
String name = UUID.randomUUID().toString(); // 任务名称
String group = GoodSecKillRemindTimer.class.getName(); // 任务所属分组
long startTime = System.currentTimeMillis() + 1000 * 5 * 60; // 秒杀开始时间
JobDetail jobDetail = JobBuilder.newJob(GoodSecKillRemindTimer.class).withIdentity(name,group).build();
jobDetail.getJobDataMap().put("goodId",goodId); // 设置任务传递商品编号参数
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(name,group).startAt(new Date(startTime)).build();//创建任务触发器
scheduler.scheduleJob(jobDetail,trigger); //将触发器与任务绑定到调度器内
}
}
说明:
1)商品业务处理逻辑;
2)商品添加后,分别执行3个任务:
2.1)构建创建商品定时任务;
2.2)构建商品库存定时任务;
2.3)构建商品秒杀提醒定时任务;
GoodController
package com.youfan.goods.control;
import com.youfan.goods.entity.GoodInfoEntity;
import com.youfan.goods.service.GoodInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/good")
public class GoodController
{
/**
* 商品业务逻辑实现
*/
@Autowired
private GoodInfoService goodInfoService;
/**
* 添加商品
* @return
*/
@RequestMapping(value = "/save")
public Long save(GoodInfoEntity good) throws Exception {
return goodInfoService.saveGood(good);
}
}
说明:
1)对外提供接口调用;
定时任务的处理
GoodAddTimer
package com.youfan.timer;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Date;
/**
* 商品添加定时任务实现类
*/
public class GoodAddTimer extends QuartzJobBean {
static Logger logger = LoggerFactory.getLogger(GoodAddTimer.class);
/**
* 定时任务逻辑实现方法
* 每当触发器触发时会执行该方法逻辑
* @param jobExecutionContext 任务执行上下文
* @throws JobExecutionException
*/
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("分布式节点quartz-cluster-node-first,商品添加完成后执行任务,任务时间:{}",new Date());
}
}
说明:
1)模拟添加完后,任务执行;
GoodSecKillRemindTimer
package com.youfan.timer;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 商品秒杀提醒定时器
* 为关注该秒杀商品的用户进行推送提醒
*/
public class GoodSecKillRemindTimer extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(GoodSecKillRemindTimer.class);
/**
* 任务指定逻辑
* @param jobExecutionContext
* @throws JobExecutionException
*/
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap(); // 获取任务详情内的数据集合
Long goodId = dataMap.getLong("goodId"); // 获取商品编号
logger.info("分布式节点quartz-cluster-node-first,开始处理秒杀商品:{},关注用户推送消息.",goodId);
}
}
说明:
1)模拟定时秒杀前提醒;
2)定时任务传递参数;
GoodStockCheckTimer
package com.youfan.timer;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Date;
/**
* 商品库存检查定时任务
*/
public class GoodStockCheckTimer extends QuartzJobBean {
static Logger logger = LoggerFactory.getLogger(GoodStockCheckTimer.class);
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:{}",new Date());
}
}
说明:
1)模拟定时检查库存任务处理;
启动类
package com.youfan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* quartz定时任务分布式节点-1
* 程序启动入口
*/
@SpringBootApplication
public class TestApplication {
private static Logger logger = LoggerFactory.getLogger(TestApplication.class);
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
logger.info("【【【【【【定时任务分布式节点 - quartz-cluster-node-first 已启动】】】】】】");
}
}
测试类
package com.youfan.test;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplicationTests {
/**
* 模拟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 {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/good/save")
.param("name","西红柿")
.param("unit","斤")
.param("price","12.88")
)
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().is(200))
.andReturn();
result.getResponse().setCharacterEncoding("UTF-8");
System.out.println(result.getResponse().getContentAsString());
}
}
控制台输出
2019-04-12 12:37:26.806 INFO 8732 --- [ main] com.youfan.TestApplication : 【【【【【【定时任务分布式节点 - quartz-cluster-node-first 已启动】】】】】】
2019-04-12 12:37:28.737 INFO 8732 --- [lerFactoryBean]] o.s.s.quartz.SchedulerFactoryBean : Starting Quartz Scheduler now, after delay of 2 seconds
2019-04-12 12:37:28.840 INFO 8732 --- [lerFactoryBean]] org.quartz.core.QuartzScheduler : Scheduler schedulerFactoryBean_$_shangwu1555043845399 started.
2019-04-12 12:39:14.717 INFO 8732 --- [ryBean_Worker-1] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:39:14 CST 2019
2019-04-12 12:39:30.172 INFO 8732 --- [ryBean_Worker-2] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:39:30 CST 2019
2019-04-12 12:39:50.528 INFO 8732 --- [ryBean_Worker-3] com.youfan.timer.GoodAddTimer : 分布式节点quartz-cluster-node-first,商品添加完成后执行任务,任务时间:Fri Apr 12 12:39:50 CST 2019
2019-04-12 12:40:00.113 INFO 8732 --- [ryBean_Worker-4] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:40:00 CST 2019
2019-04-12 12:40:30.050 INFO 8732 --- [ryBean_Worker-5] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:40:30 CST 2019
2019-04-12 12:41:00.304 INFO 8732 --- [ryBean_Worker-6] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:41:00 CST 2019
2019-04-12 12:41:30.059 INFO 8732 --- [ryBean_Worker-7] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:41:30 CST 2019
2019-04-12 12:42:00.116 INFO 8732 --- [ryBean_Worker-8] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:42:00 CST 2019
2019-04-12 12:42:30.057 INFO 8732 --- [ryBean_Worker-9] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:42:30 CST 2019
2019-04-12 12:43:00.115 INFO 8732 --- [yBean_Worker-10] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:43:00 CST 2019
2019-04-12 12:43:30.055 INFO 8732 --- [ryBean_Worker-1] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:43:30 CST 2019
2019-04-12 12:43:51.106 INFO 8732 --- [ryBean_Worker-2] com.youfan.timer.GoodSecKillRemindTimer : 分布式节点quartz-cluster-node-first,开始处理秒杀商品:1,关注用户推送消息.
2019-04-12 12:44:00.054 INFO 8732 --- [ryBean_Worker-3] com.youfan.timer.GoodStockCheckTimer : 分布式节点quartz-cluster-node-first,执行库存检查定时任务,执行时间:Fri Apr 12 12:44:00 CST 2019
说明:
1)商品添加完1分钟后执行【商品添加完成后执行任务】;
2)每个30秒执行【执行库存检查定时任务】;
3)5分钟后开始执行【开始处理秒杀商品】;
==============================
QQ群:143522604
群里有相关资源
欢迎和大家一起学习、交流、提升!
==============================