SpringBoot 整合 Quartz 定时任务框架详解

目录
  • 前言
  • 一、简单聊一聊 Quartz
    • 1.1、Quartz 概念
  • 二、SpringBoot 使用 Quartz
    • 2.1、基本步骤
    • 2.2、执行 Quartz 需要的SQL文件
    • 2.3、Controller
    • 2.4、Service 划重点
    • 2.5、实体类
    • 2.6、简单的 Job 案例
    • 2.7、那么该如何使用呢?

前言

在选择技术栈之前,一定要先明确一件事情,你真的需要用它吗?还有其他方式可以使用吗?

相比其他技术技术,优点在哪里呢?使用了之后的利与弊等等。

写这个主要是因为一直想写一下定时任务这个主题,这个算是写那篇文前期的铺垫和基础吧~

本文没有聊到 Java其他的实现定时任务的方法啥的~,只是对使用 Quartz 做了一个小实践

一、简单聊一聊 Quartz

Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。

Quartz 其实就是通过一个调度线程不断的扫描数据库中的数据来获取到那些已经到点要触发的任务,然后调度执行它的。这个线程就是 QuartzSchedulerThread类。其run方法中就是quartz的调度逻辑。

另外,这是一个Demo,木有考虑并发、多任务执行等等状态的发生及处理情况,见谅。

1.1、Quartz 概念

Quartz 的几个核心概念:

  • Job

表示一个工作,要执行的具体内容。此接口中只有一个方法

 void execute(JobExecutionContext context) 

JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。

Trigger 代表一个调度参数的配置,什么时候去调。

Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

二、SpringBoot 使用 Quartz

2.1、基本步骤

基本步骤就那些,这篇也不是高大上讲原理和流程之类的,就是偏向实操,可能一些地方在代码中含有注释,就不再贴说明了~

基本:JDK 8、SpringBoot、MybatisPlus、Quartz

创建一个 SpringBoot 项目

导入相关依赖~

 <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.5.2</version>
     <relativePath/>
 </parent>

 <properties>
     <java.version>1.8</java.version>
     <maven.compiler.source>8</maven.compiler.source>
     <maven.compiler.target>8</maven.compiler.target>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-quartz</artifactId>
     </dependency>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
     </dependency>
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
     </dependency>
     <dependency>
         <groupId>com.baomidou</groupId>
         <artifactId>mybatis-plus-boot-starter</artifactId>
         <version>3.4.1</version>
     </dependency>

     <dependency>
         <groupId>cn.hutool</groupId>
         <artifactId>hutool-all</artifactId>
         <version>5.1.4</version>
     </dependency>
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>1.2.76</version>
     </dependency>
 </dependencies>

项目结构:

2.2、执行 Quartz 需要的SQL文件

找到 quartz 需要的 sql 文件,在数据库中执行,这也是Quartz持久化的基础~

往下滑,找到你需要的sql文件即可。

执行完的结果:

在此基础上,我们再额外增加一张表,与我们可能有业务关联的信息整合,这啥啥允许为空,是方便我写测试~,并非正例

DROP TABLE IF EXISTS `sys_quartz_job`;
CREATE TABLE `sys_quartz_job`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `del_flag` int(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '删除状态',
  `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人',
  `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
  `job_class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务类名',
  `cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式',
  `parameter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数',
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  `status` int(1) NULL DEFAULT NULL COMMENT '状态 0正常 -1停止',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

2.3、Controller

我们直接从controller说起吧,从上往下开发。

其实一旦牵扯到表的操作,我们无疑就是crud四件事。

 /**
  * @Description: 定时任务在线管理
  * @author nzc
  */
 @RestController
 @RequestMapping("/quartzJob")
 @Slf4j
 public class QuartzJobController {

     @Autowired
     private IQuartzJobService quartzJobService;
     @Autowired
     private Scheduler scheduler;

     @RequestMapping(value = "/list", method = RequestMethod.GET)
     public Result<?> queryPageList(QuartzJob quartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
         Page<QuartzJob> page = new Page<QuartzJob>(pageNo, pageSize);
         IPage<QuartzJob> pageList = quartzJobService.page(page);
         return Result.ok(pageList);

     }

     @RequestMapping(value = "/add", method = RequestMethod.POST)
     public Result<?> add(@RequestBody QuartzJob quartzJob) {
List<QuartzJob> list = quartzJobService.list(new QueryWrapper<QuartzJob>().eq("job_class_name", quartzJob.getJobClassName()));
         if (list != null && list.size() > 0) {
             return Result.error("该定时任务类名已存在");
         }
         quartzJobService.saveAndScheduleJob(quartzJob);
         return Result.ok("创建定时任务成功");
     }

     @RequestMapping(value = "/edit", method = RequestMethod.PUT)
     public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
         try {
             quartzJobService.editAndScheduleJob(quartzJob);
         } catch (SchedulerException e) {
             log.error(e.getMessage(),e);
             return Result.error("更新定时任务失败!");
         }
         return Result.ok("更新定时任务成功!");
     }

     @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
     public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
         QuartzJob quartzJob = quartzJobService.getById(id);
         if (quartzJob == null) {
             return Result.error("未找到对应实体");
         }
         quartzJobService.deleteAndStopJob(quartzJob);
         return Result.ok("删除成功!");

     }

     @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
     public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
         if (ids == null || "".equals(ids.trim())) {
             return Result.error("参数不识别!");
         }
         for (String id : Arrays.asList(ids.split(","))) {
             QuartzJob job = quartzJobService.getById(id);
             quartzJobService.deleteAndStopJob(job);
         }
         return Result.ok("删除定时任务成功!");
     }

     /**
      * 暂停定时任务
      * @param jobClassName
      */
     @GetMapping(value = "/pause")
     public Result<Object> pauseJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
         QuartzJob job = null;
         try {
             job = quartzJobService.getOne(new LambdaQueryWrapper<QuartzJob>().eq(QuartzJob::getJobClassName, jobClassName));
             if (job == null) {
                 return Result.error("定时任务不存在!");
             }
             scheduler.pauseJob(JobKey.jobKey(jobClassName.trim()));
         } catch (SchedulerException e) {
             throw new MyException("暂停定时任务失败");
         }
         job.setStatus(CommonConstant.STATUS_DISABLE);
         quartzJobService.updateById(job);
         return Result.ok("暂停定时任务成功");
     }

     /**
      * 恢复定时任务
      * @param jobClassName
      */
     @GetMapping(value = "/resume")
     public Result<Object> resumeJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
         QuartzJob job = quartzJobService.getOne(new LambdaQueryWrapper<QuartzJob>().eq(QuartzJob::getJobClassName, jobClassName));
         if (job == null) {
             return Result.error("定时任务不存在!");
         }
         quartzJobService.resumeJob(job);
         //scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));
         return Result.ok("恢复定时任务成功");
     }
     /** 通过id查询*/
     @RequestMapping(value = "/queryById", method = RequestMethod.GET)
     public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
         QuartzJob quartzJob = quartzJobService.getById(id);
         return Result.ok(quartzJob);
     }
 }

2.4、Service 划重点

 public interface IQuartzJobService extends IService<QuartzJob> {
     boolean saveAndScheduleJob(QuartzJob quartzJob);
     boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;
     boolean deleteAndStopJob(QuartzJob quartzJob);
     boolean resumeJob(QuartzJob quartzJob);
 }

其中最主要的实现都是在这里:

 @Slf4j
 @Service
 public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {

     @Autowired
     private QuartzJobMapper quartzJobMapper;

     @Autowired
     private Scheduler scheduler;

     /**保存&启动定时任务*/
     @Override
     public boolean saveAndScheduleJob(QuartzJob quartzJob) {
         if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
             // 定时器添加
             this.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
         }
         // DB设置修改
         return this.save(quartzJob);
     }
     /**恢复定时任务 */
     @Override
     public boolean resumeJob(QuartzJob quartzJob) {
         schedulerDelete(quartzJob.getJobClassName().trim());
         schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
         quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
         return this.updateById(quartzJob);
     }

     /**编辑&启停定时任务 @throws SchedulerException */
     @Override
     public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
         if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
             schedulerDelete(quartzJob.getJobClassName().trim());
             schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
         }else{
             scheduler.pauseJob(JobKey.jobKey(quartzJob.getJobClassName().trim()));
         }
         return this.updateById(quartzJob);
     }

     /**删除&停止删除定时任务*/
     @Override
     public boolean deleteAndStopJob(QuartzJob job) {
         schedulerDelete(job.getJobClassName().trim());
         return this.removeById(job.getId());
     }

     /** 添加定时任务*/
     private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
         try {
             // 启动调度器
             scheduler.start();

             // 构建job信息
             JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();

             // 表达式调度构建器(即任务执行的时间)
             CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

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

             scheduler.scheduleJob(jobDetail, trigger);
         } catch (SchedulerException e) {
             throw new MyException("创建定时任务失败", e);
         } catch (RuntimeException e) {
             throw new MyException(e.getMessage(), e);
         }catch (Exception e) {
             throw new MyException("后台找不到该类名:" + jobClassName, e);
         }
     }

     /** 删除定时任务*/
     private void schedulerDelete(String jobClassName) {
         try {
             /*使用给定的键暂停Trigger 。*/
             scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
             /*从调度程序中删除指示的Trigger */
             scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
             /*从 Scheduler 中删除已识别的Job - 以及任何关联的Trigger */
             scheduler.deleteJob(JobKey.jobKey(jobClassName));
         } catch (Exception e) {
             log.error(e.getMessage(), e);
             throw new MyException("删除定时任务失败");
         }
     }
     private static Job getClass(String classname) throws Exception {
         Class<?> class1 = Class.forName(classname);
         return (Job) class1.newInstance();
     }
 }
 @Mapper
 public interface QuartzJobMapper extends BaseMapper<QuartzJob> {

 }

2.5、实体类

 @Data
 @TableName("sys_quartz_job")
 public class QuartzJob implements Serializable {

     @TableId(type = IdType.ID_WORKER_STR)
     private String id;

     private String createBy;

     private String updateBy;

     /**任务类名*/
     private String jobClassName;

     /** cron表达式 */
     private String cronExpression;
     /**  参数*/
     private String parameter;

     private String description;
     /** 状态 0正常 -1停止*/
     private Integer status;

     @TableLogic
     private Integer delFlag;
     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @TableField(fill = FieldFill.INSERT)
    private Date createTime;
     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Date updateTime;
 }

另外在这里顺带补充一下,本项目在yml中配置quartz,如下:

spring:
  ## quartz定时任务,采用数据库方式
  quartz:
    job-store-type: jdbc

2.6、简单的 Job 案例

如果调度器要执行任务,首先得要有一个任务相关滴类。

写了两个平常的案例,一个是不带参数的,一个是带参数的。

/**
 * 不带参的简单定时任务
 * @Author nzc
 */
@Slf4j
public class SampleJob implements Job {

	@Override
	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

		log.info(String.format("Ning zaichun的 普通定时任务 SampleJob !  时间:" + new Date()));
	}
}

带参数的:

 /**
  * 带参数的简单的定时任务
  * @Author nzc
  */
 @Slf4j
 public class SampleParamJob implements Job {

     /**
      * 若参数变量名修改 QuartzJobController中也需对应修改
      */
     private String parameter;

     public void setParameter(String parameter) {
         this.parameter = parameter;
     }
     @Override
     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
         log.info(String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob !   时间:" + LocalDateTime.now(), this.parameter));
     }
 }

2.7、那么该如何使用呢?

启动项目,让我们拿起来postman来测试吧,康康该如何使用,数据表在使用的时候,又有怎么样的变化~

我们直接来测试添加定时任务的接口,先来个不用参数的吧

 {
     "createBy": "nzc",
     "jobClassName": "com.nzc.quartz.job.SampleJob",
     "cronExpression": "0/10 * * * * ? ",
     "description": "每十秒执行一次",
     "status": "0"
 }

添加完之后就已经在执行了。 

此时我们将项目停止,重新启动~

调度器也会主动去检测任务信息,如果有,就会开始执行。

我们再来测测带有参数的

也是可以成功的,并且也是按照我们设定的时间执行的

其他的接口也是同样如此,根据接口的设定,将参数传入即可

到此这篇关于SpringBoot 整合 Quartz 定时任务框架详解的文章就介绍到这了,更多相关SpringBoot 整合 Quartz 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot整合Quartz实现动态配置定时任务的方法

    前言 在我们日常的开发中,很多时候,定时任务都不是写死的,而是写到数据库中,从而实现定时任务的动态配置,下面就通过一个简单的示例,来实现这个功能. 一.新建一个springboot工程,并添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency

  • SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法

    前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实现简单的定时任务功能. 下面说一下两种方式在Spring Boot 项目中的使用. Spring Schedule 实现定时任务 Spring Schedule 实现定时任务有两种方式 1. 使用XML配置定时任务, 2. 使用 @Scheduled 注解. 因为是Spring Boot 项目 可能尽量避免使用XML配置的形式,

  • SpringBoot+SpringBatch+Quartz整合定时批量任务方式

    目录 一.引言 二.代码具体实现 1.pom文件 2.application.yaml文件 3.Service实现类 4.SpringBatch配置类 5.Processor,处理每条数据 6.封装数据库返回数据的实体Bean 7.启动类上要加上注解 三.小结一下 spring-batch与quartz集成过程中遇到的问题 问题 原因 解决 一.引言 最近一周,被借调到其他部门,赶一个紧急需求,需求内容如下: PC网页触发一条设备升级记录(下图),后台要定时批量设备更新.这里定时要用到Quart

  • springboot整合quartz定时任务框架的完整步骤

    目录 Spring整合Quartz pom文件 对应的properties 文件 配置类 自定义任务类:ScheduledTask 获取spring中bean的工具类:SpringContextUtil 定时任务服务接口:QuartzService QuartzService实现类:QuartzServiceImpl ScheduledTaskRunner类 任务实体类:QuartzTask 任务service层 service实现类 任务controller 数据表 具体使用 具体效果 总结

  • springboot整合quartz实现定时任务示例

    在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的. spring支持多种定时任务的实现.我们来介绍下使用spring的定时器和使用quartz定时器 1.我们使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式. 2.使用spring的定时器: spring自带支持定时器的任务实现.其可通过简单配置来使用到简单的定时任务. @Component @Configurable @EnableScheduling p

  • SpringBoot整合Quartz实现定时任务详解

    目录 Quartz简介 核心概念 Scheduler JobDetail Job Trigger SpringBoot整合Quartz 准备数据库表 Maven相关依赖 配置文件 quartz配置类 创建任务类 创建监听类 运行结果 Quartz简介 Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.它有很多特征,如:数据库支持,集群,插件,EJB

  • SpringBoot 整合 Quartz 定时任务框架详解

    目录 前言 一.简单聊一聊 Quartz 1.1.Quartz 概念 二.SpringBoot 使用 Quartz 2.1.基本步骤 2.2.执行 Quartz 需要的SQL文件 2.3.Controller 2.4.Service 划重点 2.5.实体类 2.6.简单的 Job 案例 2.7.那么该如何使用呢? 前言 在选择技术栈之前,一定要先明确一件事情,你真的需要用它吗?还有其他方式可以使用吗? 相比其他技术技术,优点在哪里呢?使用了之后的利与弊等等. 写这个主要是因为一直想写一下定时任务

  • SpringBoot整合Shiro的代码详解

    shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/  它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shiro整合的功能!接下来就用springboot结合springmvc,mybatis,整合shiro完成对于用户登录的判定和权限的验证. 1.准备数据库表结构 这里主要涉及到五张表:用户表,角色表(用户所拥有的角色),权限表(角色所涉及到的权限),用户-角色表(用户和角色是多对多的),角色-权限表

  • SpringBoot整合Swagger2的步骤详解

    简介 swagger是一个流行的API开发框架,这个框架以"开放API声明"(OpenAPI Specification,OAS)为基础, 对整个API的开发周期都提供了相应的解决方案,是一个非常庞大的项目(包括设计.编码和测试,几乎支持所有语言). springfox大致原理: springfox的大致原理就是,在项目启动的过种中,spring上下文在初始化的过程, 框架自动跟据配置加载一些swagger相关的bean到当前的上下文中,并自动扫描系统中可能需要生成api文档那些类,

  • SpringBoot整合Shiro的方法详解

    目录 1.Shito简介 1.1 什么是shiro 1.2 有哪些功能 2.QuickStart 3.SpringBoot中集成 1.导入shiro相关依赖 2.自定义UserRealm 3.定义shiroConfig 4.新建页面进行测试 1.Shito简介 1.1 什么是shiro Apache Shiro是一个java安全(权限)框架 Shiro可以非常容易的开发出足够好的应用,其不仅可以用在javase环境,也可以用在javaee环境 shiro可以完成,认证,授权,加密,会话管理,we

  • SpringBoot整合Druid数据源过程详解

    这篇文章主要介绍了SpringBoot整合Druid数据源过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.数据库结构 2.项目结构 3.pom.xml文件 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</ar

  • SpringBoot整合MongoDB的步骤详解

    项目结构: 1.pom引入mongodb依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> 2 配置application.properties #spring.data.mongodb.host=127.0.0.1 #spr

  • springBoot整合rabbitMQ的方法详解

    引入pom <?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

  • springBoot整合redis使用案例详解

    一.创建springboot项目(采用骨架方式) 创建完成: 我们分析下pom文件中内容: 所使用到的关键依赖: <!--springBoot集成redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.5.4<

  • SpringBoot整合rockerMQ消息队列详解

    目录 Springboot整合RockerMQ 使用总结 消费模式 生产者组和消费者组 生产者投递消息的三种方式 如何保证消息不丢失 顺序消息 分布式事务 Springboot整合RockerMQ 1.maven依赖 <dependencies> <!-- springboot-web组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>

随机推荐