Spring boot整合quartz定时任

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shenzhen_zsw/article/details/89231452

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分钟后开始执行【开始处理秒杀商品】;

猜你喜欢

转载自blog.csdn.net/shenzhen_zsw/article/details/89231452