当前位置: 首页 > news >正文

Spring Boot集成RocketMQ实现普通、延时、事务消息发送接收、PULL消费模式及开启ACL | Spring Cloud 30

一、前言

在前面我们通过以下章节对RocketMQ有了基础的了解:

docker-compose 搭建RocketMQ 5.1.0 集群(双主双从模式) | Spring Cloud 28

docker-compose 搭建RocketMQ 5.1.0 集群开启ACL权限控制 | Spring Cloud 29

现在开始我们正式学习Spring Boot中集成RocketMQ使用,,在本章节主要进行对以下部分讲解说明:

  • 普通消息的发送接收
  • 延时消息的发送接收
  • 事务消息的发送接收
  • 发送端和接收端开启ACL
  • PULL模式消费及@ExtRocketMQConsumerConfiguration使用

二、项目集成RocketMQ

2.1 项目总体结构

在这里插入图片描述

2.2 引入依赖

rocketmq/pom.xml

<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.3</version>
</dependency>

2.3 配置文件

rocketmq/src/main/resources/application.yml

server:port: 8888spring:application:name: @artifactId@rocketmq:name-server: 192.168.0.30:9876producer:group: @artifactId@-groupsend-message-timeout: 60000  # 发送消息超时时间,单位:毫秒。默认为 3000retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次retry-times-when-send-async-failed: 2 # 异步发送消息时,失败重试次数。默认为 2 次retry-next-server: false # 发送消息给 Broker 时,如果发送失败,是否重试另外一台 Broker 默认为 falseaccess-key: RocketMQAdmin # Access Keysecret-key: 1qaz@WSX # Secret Keyenable-msg-trace: true # 是否开启消息轨迹功能,默认为 true 开启customized-trace-topic: RMQ_SYS_TRACE_TOPIC # 自定义消息轨迹的 Topic,默认为 RMQ_SYS_TRACE_TOPICconsumer:access-key: RocketMQAdmin # Access Keysecret-key: 1qaz@WSX # Secret Keylogging:level:org:springframework:boot:autoconfigure:logging: info

2.4主题及消费组常量

com/gm/rocketmq/component/rocketmq/TopicConstants.java

package com.gm.rocketmq.component.rocketmq;/*** 主题常量*/
public interface TopicConstants {String NORMAL_ROCKETMQ_TOPIC_TEST= "NORMAL_ROCKETMQ_TOPIC_TEST";String ORDERLY_ROCKETMQ_TOPIC_TEST= "ORDERLY_ROCKETMQ_TOPIC_TEST";String SCHEDULE_ROCKETMQ_TOPIC_TEST= "SCHEDULE_ROCKETMQ_TOPIC_TEST";String TRANSACTION_ROCKETMQ_TOPIC_TEST= "TRANSACTION_ROCKETMQ_TOPIC_TEST";String PULL_ROCKETMQ_TOPIC_TEST= "PULL_ROCKETMQ_TOPIC_TEST";String EXT_ROCKETMQ_TOPIC_TEST= "EXT_ROCKETMQ_TOPIC_TEST";String CONSUMER_GROUP = "_CONSUMER_GROUP";
}

三、各类型消息收发

3.1 普通消息

3.1.1 普通消息发送

     @Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 向rocketmq发送同步和异步消息*/@RequestMapping(value = "sendNormal", method = RequestMethod.GET)public String sendNormal() {rocketMQTemplate.send(TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + ":sync", MessageBuilder.withPayload("同步发送消息").build());rocketMQTemplate.asyncSend(TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + ":async", MessageBuilder.withPayload("异步发送消息").build(), new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {log.info("异步发送成功:{}", sendResult.getSendStatus().name());}@Overridepublic void onException(Throwable throwable) {log.info("异步发送失败:{}", throwable.getMessage());}});return "OK";}

3.1.2 普通消息接收

com/gm/rocketmq/component/rocketmq/NormalRocketMqListener.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST, consumerGroup = TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP, accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}")
public class NormalRocketMqListener implements RocketMQListener<String> {@Overridepublic void onMessage(String s) {log.info("普通订阅-接收到的信息:{}", s);}
}

@RocketMQMessageListener注解参数说明:

  • consumerGroup:消费者订阅组,它是必需的,并且必须是唯一的。
  • topic:主题名字,生产发送的主题名。
  • consumeMode:消费模式,可选择并发或有序接收消息;默认CONCURRENTLY同时接收异步传递的消息。
  • messageModel:消息模式,默认CLUSTERING集群消费;如果希望所有订阅者都接收消息,可以设置广播BROADCASTING
  • consumeThreadMax:消费者最大线程数,默认64
  • consumeTimeout:消息阻塞最长时间,默认15分钟。
  • nameServer:服务器地址,默认读取配置文件地址,可以单独为消费者设置指定位置。
  • selectorExpression:消费指定的Tag标签的业务消息。
  • ConsumerACL 功能需要在 @RocketMQMessageListener 中进行配置
  • ProducerACL 功能需要在配置文件中进行配置
  • 更多查看官方解释

3.2 顺序消息

3.2.1 顺序消息发送

    /*** 向rockertmq发送顺序消息,同步方式** @return*/@RequestMapping(value = "sendOrderlySync", method = RequestMethod.GET)public String sendOrderlySync() {// 订单列表List<OrderStep> orderList = buildOrders();for (int i = 0; i < 10; i++) {Message msg = MessageBuilder.withPayload(orderList.get(i).toString()).build();String orderId = String.valueOf(orderList.get(i).getOrderId());rocketMQTemplate.sendOneWayOrderly(TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + ":sync", msg, orderId);}return "OK";}/*** rockertmq发送顺序消息,异步方式** @return*/@RequestMapping(value = "sendOrderlyAsync", method = RequestMethod.GET)public String sendOrderlyAsync() {// 订单列表List<OrderStep> orderList = buildOrders();for (int i = 0; i < 10; i++) {Message msg = MessageBuilder.withPayload(orderList.get(i).toString()).build();String orderId = String.valueOf(orderList.get(i).getOrderId());rocketMQTemplate.syncSendOrderly(TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + ":async", msg, orderId);}return "OK";}/*** 订单的步骤*/private static class OrderStep {private long orderId;private String desc;public long getOrderId() {return orderId;}public void setOrderId(long orderId) {this.orderId = orderId;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}@Overridepublic String toString() {return "OrderStep{" + "orderId=" + orderId + ", desc='" + desc + '\'' + '}';}}/*** 生成模拟订单数据*/private List<OrderStep> buildOrders() {List<OrderStep> orderList = new ArrayList<OrderStep>();OrderStep orderDemo = new OrderStep();orderDemo.setOrderId(15103111039L);orderDemo.setDesc("创建");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111065L);orderDemo.setDesc("创建");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111039L);orderDemo.setDesc("付款");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103117235L);orderDemo.setDesc("创建");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111065L);orderDemo.setDesc("付款");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103117235L);orderDemo.setDesc("付款");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111065L);orderDemo.setDesc("完成");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111039L);orderDemo.setDesc("推送");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103117235L);orderDemo.setDesc("完成");orderList.add(orderDemo);orderDemo = new OrderStep();orderDemo.setOrderId(15103111039L);orderDemo.setDesc("完成");orderList.add(orderDemo);return orderList;}

3.2.1 顺序消息接收

com/gm/rocketmq/component/rocketmq/OrderlyRocketMqListenerA.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST,consumerGroup = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}",consumeMode = ConsumeMode.ORDERLY)
public class OrderlyRocketMqListenerA implements RocketMQListener<String> {@Overridepublic void onMessage(String s) {log.info("顺序订阅-接收到的信息:{}", s);}
}

com/gm/rocketmq/component/rocketmq/OrderlyRocketMqListenerB.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST,consumerGroup = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}",consumeMode = ConsumeMode.ORDERLY)
public class OrderlyRocketMqListenerB implements RocketMQListener<String> {@Overridepublic void onMessage(String s) {log.info("顺序订阅-接收到的信息:{}", s);}
}

3.3 延时消息

3.3.1 延时消息发送

    /*** rockertmq发送延时消息** @return*/@RequestMapping(value = "sendSchedule", method = RequestMethod.GET)public String sendSchedule() {Message msg = MessageBuilder.withPayload("延时消息").build();rocketMQTemplate.syncSendDelayTimeSeconds(TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST + ":", msg, 20);log.info("延时消息-发布时间:{}", System.currentTimeMillis());return "OK";}

3.3.2 延时消息接收

com/gm/rocketmq/component/rocketmq/ScheduleRocketMqListener.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST,consumerGroup = TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}")
public class ScheduleRocketMqListener implements RocketMQListener<MessageExt> {@Overridepublic void onMessage(MessageExt message) {String msg = "内容:" + new String(message.getBody()) + ",时间:" + (System.currentTimeMillis() - message.getBornTimestamp()) + "ms later";log.info("延时订阅-接收到的信息:{}", msg);log.info("延时消息-接受时间:{}", System.currentTimeMillis());}
}

3.4 发送端事务消息

3.4.1 事务消息发送

    /*** rockertmq发送生产端事务消息** @return*/@RequestMapping(value = "sendTransaction", method = RequestMethod.GET)public String sendTransaction() {Message msg = MessageBuilder.withPayload("事务消息").build();TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(TopicConstants.TRANSACTION_ROCKETMQ_TOPIC_TEST + ":", msg, "自定义参数");log.info("事务消息-发布结果:{} = {}", result.getTransactionId(), result.getSendStatus());return "OK";}

com/gm/rocketmq/component/rocketmq/TransactionListenerImpl.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
@RocketMQTransactionListener
class TransactionListenerImpl implements RocketMQLocalTransactionListener {private AtomicInteger transactionIndex = new AtomicInteger(0);private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();// 事务消息共有三种状态,提交状态、回滚状态、中间状态:// RocketMQLocalTransactionState.COMMIT: 提交事务,它允许消费者消费此消息。// RocketMQLocalTransactionState.ROLLBACK: 回滚事务,它代表该消息将被删除,不允许被消费。// RocketMQLocalTransactionState.UNKNOWN: 中间状态,它代表需要检查消息队列来确定状态。// executeLocalTransaction 方法来执行本地事务@Overridepublic RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {String transactionId = msg.getHeaders().get("__transactionId__").toString();log.info("执行本地事务,transactionId:{}", transactionId);int value = transactionIndex.getAndIncrement();int status = value % 3;localTrans.put(transactionId, status);log.info("获取自定义参数:{}", arg);return RocketMQLocalTransactionState.UNKNOWN;}// checkLocalTransaction 方法用于检查本地事务状态,并回应消息队列的检查请求@Overridepublic RocketMQLocalTransactionState checkLocalTransaction(Message msg) {String transactionId = msg.getHeaders().get("__transactionId__").toString();log.info("检查本地事务状态,transactionId:{}", transactionId);Integer status = localTrans.get(transactionId);if (null != status) {switch (status) {case 0:return RocketMQLocalTransactionState.UNKNOWN;case 1:return RocketMQLocalTransactionState.COMMIT;case 2:return RocketMQLocalTransactionState.ROLLBACK;}}return RocketMQLocalTransactionState.COMMIT;}
}

3.5 Pull模式消费

3.5.1 源码分析

rocketmq-spring-boot-starter中关于Pull模式消费的自动配置,
org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration

在这里插入图片描述
其中rocketmq.name-serverrocketmq.pull-consumer.grouprocketmq.pull-consumer.topic三项配置为必填项。

剩余其他配置,org.apache.rocketmq.spring.autoconfigure.RocketMQProperties.PullConsumer

在这里插入图片描述

由上可知,利用rocketmq-spring-boot-starter实现PULL模式,只支持单TopicPULL消费,要想对多个Topic进行PULL模式消费需要用到@ExtRocketMQConsumerConfiguration

3.5.2 PULL消费所需配置文件

配置文件新增pull-consumer相关配置,完整rocketmq/src/main/resources/application.yml

rocketmq:name-server: 192.168.0.30:9876producer:group: @artifactId@-groupsend-message-timeout: 60000  # 发送消息超时时间,单位:毫秒。默认为 3000retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次retry-times-when-send-async-failed: 2 # 异步发送消息时,失败重试次数。默认为 2 次retry-next-server: false # 发送消息给 Broker 时,如果发送失败,是否重试另外一台 Broker 默认为 falseaccess-key: RocketMQAdmin # Access Keysecret-key: 1qaz@WSX # Secret Keyenable-msg-trace: true # 是否开启消息轨迹功能,默认为 true 开启customized-trace-topic: RMQ_SYS_TRACE_TOPIC # 自定义消息轨迹的 Topic,默认为 RMQ_SYS_TRACE_TOPICconsumer:access-key: RocketMQAdmin # Access Keysecret-key: 1qaz@WSX # Secret Keypull-consumer:access-key: RocketMQAdmin # Access Keysecret-key: 1qaz@WSX # Secret Keytopic: PULL_ROCKETMQ_TOPIC_TESTgroup: PULL_ROCKETMQ_TOPIC_TEST_CONSUMER_GROUP

3.5.3 消息发送

    /*** 向ockertmq 消费端pull模式发生消息** @return*/@RequestMapping(value = "sendPull", method = RequestMethod.GET)public String pull() {for (int i = 0; i < 10; i++) {Message msg = MessageBuilder.withPayload("pull 消息" + i).build();rocketMQTemplate.syncSend(TopicConstants.PULL_ROCKETMQ_TOPIC_TEST + ":", msg);}for (int i = 0; i < 10; i++) {Message msg = MessageBuilder.withPayload("pull ext 消息" + i).build();rocketMQTemplate.syncSend(TopicConstants.EXT_ROCKETMQ_TOPIC_TEST + ":", msg);}return "OK";}

3.5.4 @ExtRocketMQConsumerConfiguration使用

此示例利用@ExtRocketMQConsumerConfiguration定义消费,声明消费的Topic和消费组,或声明不同name-server

利用@ExtRocketMQTemplateConfiguration定义生产者,声明不同name-server或者其他特定的属性来定义非标的RocketMQTemplate

com/gm/rocketmq/component/rocketmq/ExtRocketMQTemplate.java

import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration;
import org.apache.rocketmq.spring.core.RocketMQTemplate;/*** 可用于不同name-server或者其他特定的属性来定义非标的RocketMQTemplate,此示例定义消息Topic和消费者*/
@ExtRocketMQConsumerConfiguration(group = TopicConstants.EXT_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,topic = TopicConstants.EXT_ROCKETMQ_TOPIC_TEST)
public class ExtRocketMQTemplate extends RocketMQTemplate {
}

3.5.5 PULL模式消息接收

com/gm/rocketmq/component/rocketmq/PullConsumer.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;@Slf4j
@Component
public class PullConsumer implements CommandLineRunner {@Autowiredprivate RocketMQTemplate rocketMQTemplate;@Autowiredprivate ExtRocketMQTemplate extRocketMQTemplate;@Overridepublic void run(String... args) {while (true) {List<String> messages = rocketMQTemplate.receive(String.class, 5000);log.info("receive from rocketMQTemplate, messages={}", messages);messages = extRocketMQTemplate.receive(String.class, 5000);log.info("receive from extRocketMQTemplate, messages={}", messages);}}
}

3.6 源码

源码地址:https://gitee.com/gm19900510/springboot-cloud-example.git 中模块rocketmq

相关文章:

Spring Boot集成RocketMQ实现普通、延时、事务消息发送接收、PULL消费模式及开启ACL | Spring Cloud 30

一、前言 在前面我们通过以下章节对RocketMQ有了基础的了解&#xff1a; docker-compose 搭建RocketMQ 5.1.0 集群&#xff08;双主双从模式&#xff09; | Spring Cloud 28 docker-compose 搭建RocketMQ 5.1.0 集群开启ACL权限控制 | Spring Cloud 29 现在开始我们正式学习…...

人人都能看懂的Spring源码解析,Spring如何解决循环依赖

人人都能看懂的Spring源码解析&#xff0c;Spring如何解决循环依赖原理解析什么是循环依赖循环依赖会有什么问题&#xff1f;如何解决循环依赖问题的根本原因如何解决为什么需要三级缓存&#xff1f;Spring的三级缓存源码走读Spring的三级缓存提前暴露getSingleton方法总结往期…...

Linux上搭建Discuz论坛

一.准备工作 1.下载php*&#xff0c;mariadb-server 2.上传Discuz3.5压缩包并解压 二.搭建过程 基于redhat 9 版本和Discuz3.5&#xff0c;php8.0&#xff0c;mariadb10.5演示 一.准备工作 1.下载php*&#xff0c;mariadb-server [rootredhat9 aaa]# yum install -y php*…...

【蓝桥杯专题】 树状数组(C++ | 洛谷 | acwing | 蓝桥)

菜狗现在才开始备战蓝桥杯QAQ 文章目录【蓝桥杯专题】 &#xff08;C | 洛谷 | acwing | 蓝桥&#xff09;什么是线段数组??1264. 动态求连续区间和数星星线段树AcWing 1270. 数列区间最大值PPPPPPP【蓝桥杯专题】 &#xff08;C | 洛谷 | acwing | 蓝桥&#xff09; 什么是…...

QCefView编译配置(Windows-MSVC)(11)

QCefView编译配置&#xff08;Windows-MSVC&#xff09; 文章目录QCefView编译配置&#xff08;Windows-MSVC&#xff09;1、概述2、准备工作3、添加环境变量4、更换cef源码版本5、CMake构建6、Visual Studio编译7、安装编译后的文件8、验证编译结果更多精彩内容&#x1f449;个…...

Token原理

Q&#xff1a;分布式场景下如何生成token以及使用token的流程&#xff1a; 在分布式场景下&#xff0c;可以采用以下方式生成 token 和进行权限认证&#xff1a; 1. 生成 token&#xff1a; 使用JWT&#xff08;JSON Web Token&#xff09;生成 token。JWT 是一种基于 JSON …...

③【Java组】蓝桥杯省赛真题 持续更新中...

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 蓝桥杯真题--持续更新中...一、错误票据题目描…...

linux实验之shell编程基础

这世间&#xff0c;青山灼灼&#xff0c;星光杳杳&#xff0c;秋风渐渐&#xff0c;晚风慢慢 shell编程基础熟悉shell编程的有关机制&#xff0c;如标准流。学习Linux环境变量设置文件及其内容/etc/profile/etc/bashrc/etc/environment~/.profile~/.bashrc熟悉编程有关基础命令…...

C语言小程序:通讯录(静态版)

哈喽各位老铁们&#xff0c;今天给大家带来一期通讯录的静态版本的实现&#xff0c;何为静态版本后面会做解释&#xff0c;话不多说&#xff0c;直接开始&#xff01;关于通讯录&#xff0c;其实也就是类似于我们手机上的通讯录一样&#xff0c;有着各种各样的功能&#xff0c;…...

写CSDN博客两年半的收获--总结篇

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;练习时长两年半的java博主 &#x1f39f;️个人主页&#xff1a;君临๑ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 不知不觉间&#xff0c;在csdn写博客也有两年半的时间了&#x…...

中科亿海微FPGA应用(一、点灯)

1.软件&#xff1a; https://download.csdn.net/download/weixin_41784968/87564071 需要申请license才能使用&#xff1a;软件试用申请_软件试用申请_中科亿海微电子科技&#xff08;苏州&#xff09;有限公司 2.开发板&#xff1a; 芯片EQ6HL45&#xff0c;42.5k LUT。 3…...

ElasticSearch - SpringBoot整合ES:实现搜索结果排序 sort

文章目录00. 数据准备01. Elasticsearch 默认的排序方式是什么&#xff1f;02. Elasticsearch 支持哪些排序方式&#xff1f;03. ElasticSearch 如何指定排序方式&#xff1f;04. ElasticSearch 如何按照相关性排序&#xff1f;05. ElasticSearch 查询结果如何不按照相关性排序…...

IDEA的全新UI可以在配置里启用了,快来试试吧!

刚看到IDEA官方昨天发了这样一条推&#xff1a;IDEA的新UI可以在2022.3版本上直接使用了&#xff01;开启方法如下&#xff1a;打开IDEA的Setting界面&#xff0c;在Appearance & Behavior下有个被标注为Beta标签的New UI菜单&#xff0c;具体如下图&#xff1a;勾选Enable…...

第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移

文章目录第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移备份处于活动状态时自动进行故障转移备份不活动时的自动故障转移对各种中断场景的镜像响应响应主要中断场景的自动故障转移第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移 备份处于活动状态…...

Barra模型因子的构建及应用系列七之Liquidity因子

一、摘要 在前期的Barra模型系列文章中&#xff0c;我们构建了Size因子、Beta因子、Momentum因子、Residual Volatility因子、NonLinear Size因子和Book-to-Price因子&#xff0c;并分别创建了对应的单因子策略&#xff0c;其中Size因子和NonLinear Siz因子具有很强的收益能力…...

走进二叉树的世界 ———性质讲解

二叉树的性质和证明前言1.二叉树的概念和结构特殊的二叉树&#xff1a;二叉树的性质前言 本篇博客主要讲述的是有关二叉树的一些概念&#xff0c;性质以及部分性质的相关证明&#xff0c;如果大伙发现了啥错误&#xff0c;可以在评论区指出&#x1f618;&#x1f618; 1.二叉树…...

【SSM】Spring + SpringMVC +MyBatis 框架整合

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ SSM框架整合一、导入相关依赖二、配置web.xml文…...

【算法基础】一篇文章彻底弄懂Dijkstra算法|多图解+代码详解

博主简介&#xff1a;努力学习的大一在校计算机专业学生&#xff0c;热爱学习和创作。目前在学习和分享&#xff1a;算法、数据结构、Java等相关知识。博主主页&#xff1a; 是瑶瑶子啦所属专栏: 算法 &#xff1b;该专栏专注于蓝桥杯和ACM等算法竞赛&#x1f525;近期目标&…...

第二十三天01MySQL多表查询与事务

目录 1. 多表查询 1.1 概述 1.1.1 数据准备 1.1.2 介绍 1.1.3 分类 1.2 内连接 1.2.1 语法 1.2.2 案例演示 1.3 外连接 1.3.1 语法 1.3.2 案例演示 1.4 子查询 1.4.1 介绍 1.4.2 标量子查询 1.4.3 列子查询 1.4.4 行子查询 1.4.5 表子查询 1.5 案例 1.5.1 介…...

TCP协议详解

1.TCP的准备条件在古代的时候&#xff0c;古人们经常写书信进行交流&#xff0c;写书信的前提是你要知道这份信是要寄给谁在网络中&#xff0c;我们通过ip端口号找对目标对象&#xff0c;但是现在网站一般会对ip端口注册一个域名&#xff0c;所以我们一般就是对域名进行查找&am…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

前端工具库lodash与lodash-es区别详解

lodash 和 lodash-es 是同一工具库的两个不同版本&#xff0c;核心功能完全一致&#xff0c;主要区别在于模块化格式和优化方式&#xff0c;适合不同的开发环境。以下是详细对比&#xff1a; 1. 模块化格式 lodash 使用 CommonJS 模块格式&#xff08;require/module.exports&a…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...