SpringBoot 整合Quartz定时任务管理【SpringBoot系列18】

news2024/10/1 22:49:56

SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。
程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCloud 微服务系列项目开发

Quartz是由Java语言编写,是OpenSymphony开源组织在Job scheduling领域的项目。

在这里插入图片描述

1 项目信息

首先是在项目的 pom.xml 文件中添加依赖如下

 <!-- 定时任务-->
 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz -->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-quartz</artifactId>
     <version>2.7.9</version>
 </dependency>

 <dependency>
     <groupId>com.google.code.gson</groupId>
     <artifactId>gson</artifactId>
 </dependency>

然后添加了下定时任务的配置信息


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * 定时任务配置
 *
 * @author 早起的年轻人
 * @since 2.0.0 2023-04-20
 */
@Configuration
public class ScheduleConfig {

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);

        //quartz参数
        Properties prop = new Properties();
        //#调度器实例名称
        prop.put("org.quartz.scheduler.instanceName", "RenrenScheduler");
        //#调度器实例编号自动生成
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        //线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "20");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        //JobStore配置
        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
        //集群配置 开启分布式部署
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");

        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");

        //PostgreSQL数据库,需要打开此注释
        //prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
//        prop.put(" org.quartz.jobStore.driverDelegateClass "," org.quartz.impl.jdbcjobstore.StdJDBCDelegate");

        factory.setQuartzProperties(prop);

        factory.setSchedulerName("RenrenScheduler");
        //延时启动
        factory.setStartupDelay(10);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);
        //设置自动启动,默认为true
        factory.setAutoStartup(true);

        return factory;
    }
}

然后添加 Quartz 所需要的表结构

/*
 Navicat Premium Data Transfer

 Source Server         : mac-docker-1
 Source Server Type    : MySQL
 Source Server Version : 50725
 Source Host           : 127.0.0.1:3306
 Source Schema         : spring_boot

 Target Server Type    : MySQL
 Target Server Version : 50725
 File Encoding         : 65001

 Date: 19/03/2023 15:00:20
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for QRTZ_BLOB_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;
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,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_CALENDARS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CALENDARS`;
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 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_CRON_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;
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(200) NOT NULL,
  `TIME_ZONE_ID` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_FIRED_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;
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` int(11) NOT NULL,
  `STATE` varchar(16) NOT NULL,
  `JOB_NAME` varchar(200) DEFAULT NULL,
  `JOB_GROUP` varchar(200) DEFAULT NULL,
  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_JOB_DETAILS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
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) DEFAULT 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,
  PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_LOCKS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_LOCKS`;
CREATE TABLE `QRTZ_LOCKS` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `LOCK_NAME` varchar(40) NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;
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 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_SCHEDULER_STATE
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
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 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;
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`),
  CONSTRAINT `QRTZ_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;
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) DEFAULT NULL,
  `STR_PROP_2` varchar(512) DEFAULT NULL,
  `STR_PROP_3` varchar(512) DEFAULT NULL,
  `INT_PROP_1` int(11) DEFAULT NULL,
  `INT_PROP_2` int(11) DEFAULT NULL,
  `LONG_PROP_1` bigint(20) DEFAULT NULL,
  `LONG_PROP_2` bigint(20) DEFAULT NULL,
  `DEC_PROP_1` decimal(13,4) DEFAULT NULL,
  `DEC_PROP_2` decimal(13,4) DEFAULT NULL,
  `BOOL_PROP_1` varchar(1) DEFAULT NULL,
  `BOOL_PROP_2` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for QRTZ_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_TRIGGERS`;
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) DEFAULT NULL,
  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PRIORITY` int(11) DEFAULT NULL,
  `TRIGGER_STATE` varchar(16) NOT NULL,
  `TRIGGER_TYPE` varchar(8) NOT NULL,
  `START_TIME` bigint(13) NOT NULL,
  `END_TIME` bigint(13) DEFAULT NULL,
  `CALENDAR_NAME` varchar(200) DEFAULT NULL,
  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,
  `JOB_DATA` blob,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `SCHED_NAME` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  CONSTRAINT `QRTZ_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;

本文章接 SpringBoot ElasticSearch 实现订单的分页查询 【SpringBoot系列17】

2 服务启动时 加载定时任务

ScheduleJobService.java

public interface ScheduleJobService extends IService<ScheduleJobEntity> {

	/** 保存定时任务*/
	boolean newObj(ScheduleJobEntity scheduleJob);
	
	/**更新定时任务*/
	void update(ScheduleJobEntity scheduleJob);
}

ScheduleJobServiceImpl.java 实现类

@Service("scheduleJobService")
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
    @Resource
    private Scheduler scheduler;

    /**
     * 项目启动时,初始化定时器
     */
    @PostConstruct
    public void init() {
        //查询当前所有的定时任务
        List<ScheduleJobEntity> scheduleJobList = this.list(new QueryWrapper<>());
        try {
            scheduler.clear();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        for (ScheduleJobEntity scheduleJob : scheduleJobList) {
            //获取任务的表达式触发器
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
            //如果不存在,则创建
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }
}

新建定时任务与更新定时任务如下:

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean newObj(ScheduleJobEntity scheduleJob) {
        scheduleJob.setCreateTime(new Date());
        //设置状态 默认是启动
        scheduleJob.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
        //cron表达式
        String cronExpression = scheduleJob.getCronExpression();
        //验证
        boolean valid =  CronExpression.isValidExpression(cronExpression);
        if(!valid){
            throw new RuntimeException("cron 表达式不正确");
        }
        //保存任务
        this.save(scheduleJob);
        //构建job信息
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ScheduleJobEntity scheduleJob) {
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        //更新数据库
        this.updateById(scheduleJob);
    }

ScheduleJobEntity.java 类

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

/**
 * 定时任务
 */
@TableName("schedule_job")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ScheduleJobEntity implements Serializable {
	private static final long serialVersionUID = 1L;
	
	/**
	 * 任务调度参数key
	 */
    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
	
	/**
	 * 任务id
	 */
	@TableId
	private Long jobId;

	/**
	 * spring bean名称
	 */
	private String beanName;
	
	/**
	 * 方法名
	 */
	private String methodName;
	
	/**
	 * 参数
	 */
	private String params;
	
	/**
	 * cron表达式
	 */
	private String cronExpression;

	/**
	 * 任务状态
	 */
	private Integer status;

	/**
	 * 备注
	 */
	private String remark;

	/**
	 * 创建时间
	 */
	private Date createTime;

}

3 定时任务核心调度 ScheduleUtils

/**
 * 定时任务工具类
 *
 * @author 早起的年轻人
 * @since 1.2.0 2022-11-28
 */
public class ScheduleUtils {
    private final static String JOB_NAME = "TASK_";

    /**
     * 获取触发器key
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }

    /**
     * 获取jobKey
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(JOB_NAME + jobId);
    }

    /**
     * 获取表达式触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
        }
    }

    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            JobKey jobKey = getJobKey(scheduleJob.getJobId());
            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(jobKey).build();

            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
            		.withMisfireHandlingInstructionDoNothing();

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder).build();

            Gson gson = new Gson();
            //放入参数,运行时的方法可以获取
            jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, gson.toJson(scheduleJob));

            scheduler.scheduleJob(jobDetail, trigger);

            //暂停任务
            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
            	pauseJob(scheduler, scheduleJob.getJobId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("创建定时任务失败 ", e);
        }
    }

    /**
     * 更新定时任务
     */
    public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());

            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
            		.withMisfireHandlingInstructionDoNothing();

            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());

            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            Gson gson = new Gson();
            //参数
            trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, gson.toJson(scheduleJob));

            scheduler.rescheduleJob(triggerKey, trigger);

            //暂停任务
            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
            	pauseJob(scheduler, scheduleJob.getJobId());
            }

        } catch (SchedulerException e) {
            throw new RuntimeException("更新定时任务失败", e);
        }
    }

    /**
     * 立即执行任务
     */
    public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
        	//参数
        	JobDataMap dataMap = new JobDataMap();
            Gson gson = new Gson();
        	dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY,gson.toJson(scheduleJob));

            scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException("立即执行定时任务失败 "+e.getMessage(), e);
        }
    }

    /**
     * 暂停任务
     */
    public static void pauseJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暂停定时任务失败", e);
        }
    }

    /**
     * 恢复任务
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暂停定时任务失败", e);
        }
    }

    /**
     * 删除定时任务
     */
    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("删除定时任务失败", e);
        }
    }
}

项目源码在这里 :https://gitee.com/android.long/spring-boot-study/tree/master/biglead-api-13-quartz
有兴趣可以关注一下公众号:biglead


  1. 创建SpringBoot基础项目
  2. SpringBoot项目集成mybatis
  3. SpringBoot 集成 Druid 数据源【SpringBoot系列3】
  4. SpringBoot MyBatis 实现分页查询数据【SpringBoot系列4】
  5. SpringBoot MyBatis-Plus 集成 【SpringBoot系列5】
  6. SpringBoot mybatis-plus-generator 代码生成器 【SpringBoot系列6】
  7. SpringBoot MyBatis-Plus 分页查询 【SpringBoot系列7】
  8. SpringBoot 集成Redis缓存 以及实现基本的数据缓存【SpringBoot系列8】
  9. SpringBoot 整合 Spring Security 实现安全认证【SpringBoot系列9】
  10. SpringBoot Security认证 Redis缓存用户信息【SpringBoot系列10】
  11. SpringBoot 整合 RabbitMQ 消息队列【SpringBoot系列11】
  12. SpringBoot 结合RabbitMQ与Redis实现商品的并发下单【SpringBoot系列12】
  13. SpringBoot 雪花算法生成商品订单号【SpringBoot系列13】
  14. SpringBoot RabbitMQ 延时队列取消订单【SpringBoot系列14】
  15. SpringBoot RabbitMQ 商品秒杀【SpringBoot系列15】
  16. SpringBoot ElasticSearch 【SpringBoot系列16】
  17. SpringBoot ElasticSearch 实现订单的分页查询 【SpringBoot系列17】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/428416.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【环境搭建:onnx模型部署】onnxruntime-gpu安装与测试(python)

ONNX模型部署环境创建1. onnxruntime 安装2. onnxruntime-gpu 安装2.1 方法一&#xff1a;onnxruntime-gpu依赖于本地主机上cuda和cudnn2.2 方法二&#xff1a;onnxruntime-gpu不依赖于本地主机上cuda和cudnn2.2.1 举例&#xff1a;创建onnxruntime-gpu1.14.1的conda环境2.2.2 …

Spring整合MyBatis与JUnit

Spring整合 想必到现在我们已经对Spring有一个简单的认识了&#xff0c;Spring有一个容器&#xff0c;叫做IoC容器&#xff0c;里面保存bean。在进行企业级开发的时候&#xff0c;其实除了将自己写的类Spring管理之外&#xff0c;还有一部分重要的工作就是使用第三方的技术。前…

Spring —— Spring Boot 创建和使用

JavaEE传送门JavaEE Spring —— Spring简单的读取和存储对象 Ⅱ Spring —— Bean 作用域和生命周期 目录Spring Boot 创建和使用Spring BootSpring Boot 项目创建使用 IDEA 创建网页版创建Spring Boot 目录介绍运行 Spring Boothello world约定大于配置Spring Boot 创建和使…

关于SeaDAS的安装教程以及使用问题笔记

2022年硕士研究生最后半个学期&#xff0c;已经交完了毕业论文&#xff0c;因为觉得工作以后会用到SeaDAS就拿出了一些时间学习&#xff0c;现在已经工作快一年了&#xff0c;而工作中也并没有用到这个软件&#xff0c;估计以后也不会用到了吧。现在把当时学习整理的一些笔记分…

字符串匹配算法(BFKMP)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构初阶&#xff08;C实现&#xff09;】 目录字符串匹配算法BF算法代码实现KMP算法代码实现nextval数组改进字符串匹配算法 在学…

MySQL 库操作

目录 创建数据库 语法 案例 字符集和校验规则&#xff08;建数据库/建表用&#xff09; 查看系统默认字符集以及校验规则 db.opt 更改 查看数据库支持的字符集 查看数据库支持的字符集校验规则 校验规则对数据库的影响 排升序 操纵数据库 查看数据库 显示创建语…

[计算机图形学]几何:隐式显式表示(前瞻预习/复习回顾)

一、前言 本篇我们将开启GAMES101几何部分的讲解的第一讲解&#xff0c;也是几何的基本表示&#xff0c;现实中有非常多的几何&#xff0c;如布料&#xff0c;绝对光滑的曲面&#xff0c;水滴&#xff0c;毛发&#xff0c;微观的细胞等等非常复杂的几何&#xff0c;那么如何在…

十分钟在 macOS 快速搭建 Linux C/C++ 开发环境

有一个使用了 Epoll 的 C 项目&#xff0c;笔者平时用的 Linux 主力开发机不在身边&#xff0c;想在 macOS 上开发调试&#xff0c;但是没有 Linux 虚拟机。恰好&#xff0c;JetBrains CLion 的 Toolchains 配置除了使用本地环境&#xff0c;还支持 SSH、Docker。 笔者使用 CL…

Zabbix的介绍与部署

目录 zabbix zabbix简介 zabbix主要功能 zabbix主要特点 zabbix运行机制 zabbix架构 1.sever-client架构 2.sever-proxy-client架构 3.master-node-client架构 如何进行数据采集 zabbix工作原理 zabbix监控模式 安装zabbix5.0 部署zabbix服务端 web页面测试 部…

系统集成项目管理工程师 笔记(第二章:信息系统集成及服务管理)

文章目录2.3.1 ITIL与IT服务管理&#xff08;ITSM&#xff09; 117ITSM三个根本目标2.3.2 ITSS与信息技术服务 121ITSS的4个组成要素和5个生命周期2.3.3 信息系统审计 127信息系统审计是建立在以下 4 个理论基础之上的信息系统审计流程示意图审计步骤第2章 信息系统集成及服务管…

怎么设置动态壁纸?这样做就行!

案例&#xff1a;怎么设置动态壁纸 【朋友们&#xff0c;我的壁纸一直都是静态的&#xff0c;最近感觉有点审美疲劳了&#xff0c;想换些好看的动态壁纸&#xff0c;有朋友知道应该如何设置动态壁纸吗&#xff1f;】 经常使用电脑的朋友可能会觉得一直用同一张壁纸会感觉审美…

通过两阶段知识学习多种不利天气排除

论文&#xff1a;Learning Multiple Adverse Weather Removal via Two-stage Knowledge Learning and Multi-contrastive Regularization: Toward a Unified Model【通过两阶段知识学习多种不利天气排除】 论文下载地址&#xff1a;https://openaccess.thecvf.com/content/CVP…

过去的90天,ODC 发生了哪些新的改变?

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 关于作者 胡智娟 OceanBase 产品经理 主要负责 OceanBase 生态工具数据研发、迁移评估方向的产品工作&#xff0c;在蚂蚁集团有多年数据库管理实战经验&#xff0c;对日常研发及运维痛点有较深感悟…

个人-计算机操作系统第五章

第五章 虚拟存储器 一、章节练习 1.系统抖动是指( )。 A. 使用机器时&#xff0c;千万屏幕闪烁的现象 B. 刚被调出的页面又立刻被调入所形成的频繁调入调出现象 C. 系统盘不净&#xff0c;千万系统不稳定的现象 D. 由于内存分配不当&#xff0c;偶然造成内存不够…

史上最全的快速排序方法--Hoare快排 挖坑法快排 二路快排 三路快排 非递归快排

一.快速排序 1.基本介绍 快速排序&#xff08;Quicksort&#xff09;由英国计算机科学家Tony Hoare于1959年发明&#xff0c;是一种经典的排序算法&#xff0c;被广泛应用于计算机科学领域。快速排序&#xff08;Quick Sort&#xff09;是一种常见的基于比较的排序算法&#…

阿里云李飞飞:数据库将迎来“四化”趋势

伴随着数字经济的高速发展&#xff0c;越来越多的企业管理者都开始认识到数据才是企业最宝贵的资产&#xff0c;并为此不断加速企业的数字化转型与升级。而在数据库领域&#xff0c;云原生已经当仁不让地成为了当下最炙手可热的技术趋势之一。那么在云原生的时代大潮之下&#…

C++ STL之string容器

目录一、C与C字符串的差别二、string类对象的容量操作三、string类中的常见API总览1.构造2.赋值重载赋值操作符 成员函数 assign3.存取重载下标获取操作符 [ ]成员函数 at4.拼接重载复合操作符 成员函数 append5.查找成员函数 find成员函数 rfind成员函数 replace6.比较成员函数…

python接口自动化测试 之mock模块基本使用介绍

目录 mock作用 解决依赖问题&#xff0c;达到解耦作用 模拟复杂业务的接口 单元测试 前后端联调 mock类解读 mock实际使用 一个未开发完成的功能如何测试&#xff1f; 一个完成开发的功能如何测试&#xff1f; mock装饰器 mock作用 解决依赖问题&#xff0c;达到解耦…

AutoCAD2021安装教程图解+系统要求

AutoCAD2021具有完善的图形绘制功能&#xff0c;是一款非常实用的CAD图形制作软件&#xff0c;这款软件在业内也拥有极高的知名度&#xff0c;基本上绘图专业相关人员都会使用这款软件&#xff0c;来进行设计绘图。在软件中&#xff0c;为用户打造了超多实用的工具&#xff0c;…

python学习路线图(2023详细版)建议收藏

Python是一种面向对象的程序设计语言&#xff0c;由Python3演变而来&#xff0c;Python的目标是简单、可扩展并且高效。Python可以作为 Web应用程序、桌面应用程序和桌面 Web应用程序开发的理想语言&#xff0c;并且有很多优点它可以使用一些简单的参数和函数、Python支持多种数…