如果一张车票,被A乘客选中,且停留在付款页面,那么这张车票是不能出现在其他购票用户是不能购买的,因为该车票已经暂时被锁定,那么假如A乘客迟迟停留在付款页面,20秒钟过后,还未支付该订单,那么系统的定时器的功能会执行调度器去查询支付状态,如果未支付,我们的定时器工作要实现此功能,将车票解除锁定,重新改为可用的状态,那么A用户和其他的用户又能够购买该票。这时候就需要quartz自动调度器来实现。
本项目实例是基于idea开发软件进行编码,在spring boot中结合quartz使用,如果订单在20秒钟查询编号为1的车票,如果十秒之后还在付款,则取消该车票订单,将车票的锁定状态重新改为可用。
步骤:
新建Spring Boot项目
1.在Mysql的quartz数据库建立4表和在idea建相关包
2.使用项目内部的mybatis插件,将下列的sql导入到Mysql运行,然后借助插件自动生成实体类和mapper 使用教程
-- 需要定时器执行操作的实体类,这里是以订单表为例
create table t_order
(
order_id int primary key auto_increment, -- 订单ID
order_no varchar(50) not null, -- 订单编号
customer_id int not null, -- 客户ID
order_status int not null, -- 状态:0 待付款 1 已付款 2 已取消(客户) 3 已取消(卖家) 4 已取消(付款超时)
create_timestamp timestamp NULL default CURRENT_TIMESTAMP -- 创建日期时间:默认为系统当前时间
);
-- 注意:job_name存放的任务类的全路径,在quartz中通过jobName和jobGroup来确定trigger的唯一性,所以这两列为联合唯一索引
create table t_schedule_trigger
(
id int primary key auto_increment, -- ID
cron varchar(200) not null, -- 时间表达式
status char(1) not null, -- 使用状态 0:禁用 1:启用
job_name varchar(200) not null, -- 任务名称
job_group varchar(200) not null, -- 任务分组
unique index(job_name,job_group)
);
-- 额外添加到任务中的参数
create table t_schedule_trigger_param
(
param_id int primary key auto_increment, -- ID
name varchar(200) not null, -- 参数名
value varchar(512), -- 参数值
schedule_trigger_id int not null, -- 外键:引用t_schedule_trigger(id)
foreign key(schedule_trigger_id) references t_schedule_trigger(id)
);
注意生成之后的xml文件中配置的包的全限定名是否和项目一致。
3.在quartz包新建PayTicketJob.java接口,在订单支付状态是正在支付的状态,如果此状态持续20秒钟,那么这个工作类会去修改此票的状态。
此类需要调用:
OrderMapper.java接口的查询订单的selectPay和updateByPrimaryKey方法
ScheduleTriggerMapper.java接口的updateByPrimaryKey方法
selectPay:根据车票的id去查询到该订单的状态
updateByPrimaryKey:修改订单的状态
updateByPrimaryKey:修改触发器的状态
这里使用的调度器是表达式触发器
触发器的表达式生成网址:在线生成cron触发器的表达式网址
PayTicketJob.java
package com.springboot.ssm.quartz;
import com.springboot.ssm.mapper.OrderMapper;
import com.springboot.ssm.mapper.ScheduleTriggerMapper;
import com.springboot.ssm.model.Order;
import com.springboot.ssm.model.ScheduleTrigger;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author 小思
* @PackageName:com.springboot.ssm.quartz
* @ClassName: PayTicketJob
* @Description:十秒钟之后如果还在支付状态,则取消改订单的调度
* @date 2018/11/25 9:43
*/
//启用Lombok的Slf4j输出日志
@Slf4j
@Component
public class PayTicketJob implements Job {
static int count = 0;
@Autowired
private OrderMapper orderMapper;
@Autowired
private ScheduleTriggerMapper scheduleTriggerMapper;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("支付检查任务正在执行。。。" + new Date().toLocaleString());
//在付款页面的时候触发这个触发器
//查询3号车票票的支付状态(假如3号票被1号顾客购买了)
Order o = orderMapper.selectPay(3);
//支付状态有三种 0:未支付 1:正在支付 2:支付成功
//二十秒钟之后如未支付,则将车票状态修改,重新入库
if (o.getOrderStatus() == 1 && count == 2) {
o.setOrderStatus(0);
int n = orderMapper.updateByPrimaryKey<