多个springboot整合使用rabbitmq(使用注解的方式)
一、简述
先参考单个springboot使用rabbitmq和了解rabbitmq的五种模式
单个springboot整合rabbitmq_java-zh的博客-CSDN博客
二、创建项目
1、先创建两个springboot项目,一个做生产者,一个做消费者
2、导包(生产者和消费者对应的内容都是一样)
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.1</version><relativePath/></parent><groupId>com.mq</groupId><artifactId>mqcloud</artifactId><version>0.0.1-SNAPSHOT</version><properties><spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version><java.version>1.8</java.version><spring-boot.version>2.5.3</spring-boot.version><lombok.version>1.18.14</lombok.version><mybaits.plus.version>3.3.2</mybaits.plus.version><alibaba.json.version>1.2.75</alibaba.json.version><spring-cloud-starter-bootstrap.version>3.0.2</spring-cloud-starter-bootstrap.version></properties><!-- <dependencyManagement>--><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--AOP--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!--bootstrap 启动器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>${spring-cloud-starter-bootstrap.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${alibaba.json.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><optional>true</optional></dependency><!--jjwt--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${spring-cloud-alibaba.version}</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring-cloud-alibaba.version}</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><!--zhong 基础jar--><dependency><groupId>com.common</groupId><artifactId>base</artifactId><version>1.0-SNAPSHOT</version></dependency><!--消息队列 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>3.0.4</version></dependency></dependencies><!-- </dependencyManagement>--></project>
3、编写配置文件
这里的配置文件生产者和消费者都一样
spring:rabbitmq:#如果是集群,用,隔开connection-timeout: 15000username: adminpassword: 123456#虚拟host,可以不设置virtual-host: /listener:simple:acknowledge-mode: auto #manual:手动处理 auto:自动处理#消费端监听个数(即@RabbitListenter开启几个线程去处理)concurrency: 10#消费端监听的最大个数max-concurrency: 10prefetch: 5default-requeue-rejected: true #消费不成功的消息,拒绝入队retry:enabled: true #开启消息重试max-attempts: 4 #重试次数max-interval: 10000 #重试最大间隔时间initial-interval: 2000 #重试初始间隔时间#消息确认方式,通过correlated来确认publisher-confirm-type: correlatedpublisher-returns: truehost: 192.168.139.128port: 5672
rabbitmq:#订阅模式(扇形模式) fanout:exchange:#交换机名称name1: exchange.fanoutqueue:#通道名称name1: exchange.fanout.queue_1name2: exchange.fanout.queue_2#交换机模式 direct:exchange:name1: exchange.directqueue:name1: exchange.direct.queue_1name2: exchange.direct.queue_2routing:name1: exchange.direct.routing.1name2: exchange.direct.routing.2#主题模式 topic:exchange: name1: exchange.topicqueue:name1: exchange.topic.queue_1name2: exchange.topic.queue_2routing:name1: '#.routingkey.#'name2: routingkey.*
三、编码代码和测试结果
这里以rabbitmq的订阅模式(扇形模式)、路由器模式、主题模式为案例
3.1 扇形模式
生产者
@Autowired
private RabbitTemplate rabbitTemplate;// 订阅模式的交换机名称
@Value("${rabbitmq.fanout.exchange.name1}")private String exchangeName;/*** 订阅模式(扇形模式)生产者** @param context*/
@GetMapping("/fanout/{context}")
public void sendMessage(@PathVariable String context) {System.out.println("需要发送得内容为:" + context);rabbitTemplate.convertAndSend(exchangeName, "", context);
}
消费者
注意:消费者绑定交换机和通道的值必须是固定常量值,所以我们直接从配置文件中读取
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),value = @Queue(value = "${rabbitmq.fanout.queue.name1}")))@RabbitHandlerpublic void consumerFanoutExchange(String context) {System.out.println("订阅模式,通道一接收到的内容为内容:" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),value = @Queue(value = "${rabbitmq.fanout.queue.name2}")))@RabbitHandlerpublic void consumerFanoutExchange2(String context) {System.out.println("订阅模式,通道二接收到的内容为内容:" + context);
}
3.2 路由器模式
生产者
@Autowired
private RabbitTemplate rabbitTemplate;// 路由器模式的交换机名称
@Value("${rabbitmq.direct.exchange.name1}")
private String directName;// 路由器模式的路由key1
@Value("${rabbitmq.direct.routing.name1}")
private String directRoutingKeyName1;//路由器模式的路由key2
@Value("${rabbitmq.direct.routing.name2}")
private String directRoutingKeyName2;/*** 路由器模式* @param context* @param routingkey*/
@GetMapping("/direct")
public void sendMessageDirect(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {if (1 == routingkey) {rabbitTemplate.convertAndSend(directName, directRoutingKeyName1, context);} else if (2 == routingkey) {rabbitTemplate.convertAndSend(directName, directRoutingKeyName2, context);} else {System.out.println("数据非法");}
}
消费者
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),value = @Queue(value = "${rabbitmq.direct.queue.name1}"),key = "${rabbitmq.direct.routing.name1}"))public void exchangeDirectRoutingKey1(String context, Message message) {System.out.println("key1:" + message.getMessageProperties().getReceivedRoutingKey());System.out.println("路由器模式1 接收到的消息为:" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),value = @Queue(value = "${rabbitmq.direct.queue.name2}"),key = "${rabbitmq.direct.routing.name2}"))public void exchangeDirectRoutingKey2(String context, Message message) {System.out.println("key2:" + message.getMessageProperties().getReceivedRoutingKey());System.out.println("路由器模式2 接收到的消息为" + context);}
3.3 主题模式
生产者
// 主题模式的交换机名称@Value("${rabbitmq.topic.exchange.name1}")private String topicName;//用来匹配主题模式对应的keypublic static final String EXCHANGE_TOPIC_CASE_KEY_1 = "topic.routingkey.case1";//如果case_key_2这样写,那么绑定case_key_1的队列一样会接收到,因为case_key_2也一样和key1匹配上public static final String EXCHANGE_TOPIC_CASE_KEY_2 = "routingkey.case2";@GetMapping("/topic")public void sendMessageTopic(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {if (1 == routingkey) {rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_1, context + routingkey);} else if (2 == routingkey) {rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_2, context + routingkey);} else {System.out.println("数据非法");}}
消费者
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),value = @Queue(value = "${rabbitmq.topic.queue.name1}"),key = "${rabbitmq.topic.routing.name1}"))@RabbitHandlerpublic void exchangeTopicRoutingKey1(String context, Message message) {System.out.println("key1:"+message.getMessageProperties().getReceivedRoutingKey());System.out.println("主题模式1:接收的内容为:"+ context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),value = @Queue(value = "${rabbitmq.topic.queue.name2}"),key = "${rabbitmq.topic.routing.name2}"))@RabbitHandlerpublic void exchangeTopicRoutingKey2(String context, Message message) {System.out.println("key2:"+message.getMessageProperties().getReceivedRoutingKey());System.out.println("主题模式2:接收的内容为:"+ context);}
3.4 全量代码
生产者
@RestController
@RequiredArgsConstructor
@RequestMapping("/test/mq")
public class ProductController {private final RabbitTemplate rabbitTemplate;// 订阅模式的交换机名称@Value("${rabbitmq.fanout.exchange.name1}")private String exchangeName;// 路由器模式的交换机名称@Value("${rabbitmq.direct.exchange.name1}")private String directName;// 路由器模式的路由key1@Value("${rabbitmq.direct.routing.name1}")private String directRoutingKeyName1;//路由器模式的路由key2@Value("${rabbitmq.direct.routing.name2}")private String directRoutingKeyName2;// 主题模式的交换机名称@Value("${rabbitmq.topic.exchange.name1}")private String topicName;//用来匹配主题模式对应的keypublic static final String EXCHANGE_TOPIC_CASE_KEY_1 = "topic.routingkey.case1";//如果case_key_2这样写,那么绑定case_key_1的队列一样会接收到,因为case_key_2也一样和key1匹配上public static final String EXCHANGE_TOPIC_CASE_KEY_2 = "routingkey.case2";/*** 订阅模式(扇形模式)生产者** @param context*/@GetMapping("/fanout/{context}")public void sendMessage(@PathVariable String context) {System.out.println("需要发送得内容为:" + context);rabbitTemplate.convertAndSend(exchangeName, "", context);}/*** 路由器模式* @param context* @param routingkey*/@GetMapping("/direct")public void sendMessageDirect(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {if (1 == routingkey) {rabbitTemplate.convertAndSend(directName, directRoutingKeyName1, context);} else if (2 == routingkey) {rabbitTemplate.convertAndSend(directName, directRoutingKeyName2, context);} else {System.out.println("数据非法");}}@GetMapping("/topic")public void sendMessageTopic(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {if (1 == routingkey) {rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_1, context + routingkey);} else if (2 == routingkey) {rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_2, context + routingkey);} else {System.out.println("数据非法");}}
}
消费者
@Component
public class ConsumerTest {@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),value = @Queue(value = "${rabbitmq.fanout.queue.name1}")))@RabbitHandlerpublic void consumerFanoutExchange(String context) {System.out.println("订阅模式,通道一接收到的内容为内容:" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),value = @Queue(value = "${rabbitmq.fanout.queue.name2}")))@RabbitHandlerpublic void consumerFanoutExchange2(String context) {System.out.println("订阅模式,通道二接收到的内容为内容:" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),value = @Queue(value = "${rabbitmq.direct.queue.name1}"),key = "${rabbitmq.direct.routing.name1}"))public void exchangeDirectRoutingKey1(String context, Message message) {System.out.println("key1:" + message.getMessageProperties().getReceivedRoutingKey());System.out.println("路由器模式1 接收到的消息为:" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),value = @Queue(value = "${rabbitmq.direct.queue.name2}"),key = "${rabbitmq.direct.routing.name2}"))public void exchangeDirectRoutingKey2(String context, Message message) {System.out.println("key2:" + message.getMessageProperties().getReceivedRoutingKey());System.out.println("路由器模式2 接收到的消息为" + context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),value = @Queue(value = "${rabbitmq.topic.queue.name1}"),key = "${rabbitmq.topic.routing.name1}"))@RabbitHandlerpublic void exchangeTopicRoutingKey1(String context, Message message) {System.out.println("key1:"+message.getMessageProperties().getReceivedRoutingKey());System.out.println("主题模式1:接收的内容为:"+ context);}@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),value = @Queue(value = "${rabbitmq.topic.queue.name2}"),key = "${rabbitmq.topic.routing.name2}"))@RabbitHandlerpublic void exchangeTopicRoutingKey2(String context, Message message) {System.out.println("key2:"+message.getMessageProperties().getReceivedRoutingKey());System.out.println("主题模式2:接收的内容为:"+ context);}}
相关文章:
多个springboot整合使用rabbitmq(使用注解的方式)
一、简述 先参考单个springboot使用rabbitmq和了解rabbitmq的五种模式 单个springboot整合rabbitmq_java-zh的博客-CSDN博客 二、创建项目 1、先创建两个springboot项目,一个做生产者,一个做消费者 2、导包(生产者和消费者对应的内容都是一样) <…...
《Effective C++中文版,第三版》读书笔记2
条款06:若不想使用编译器自动生成的函数,就该明确拒绝 为驳回编译器自动()提供的机能,可将相应的成员函数声明为私有的,同时不实现它。 #include <iostream>class MyClass { public:MyClass(int in…...
虫情测报系统的工作原理及功能优势
KH-CQPest虫情测报系统能够在不对虫体造成任何破坏的情况下,无公害的杀死虫子,利用高倍显微镜和高清摄像头拍摄虫体照片,并将虫体照片发送到远端平台,让工作人员无需要到现场,通过平台就可以观察害虫的种类和数量&…...
UWB定位技术详细介绍
UWB(Ultra-Wideband)定位技术是一种通过利用信号的超宽频带特性进行高精度定位的技术。其原理是通过测量信号在空间传播中的时间延迟差异来计算物体的位置。 UWB技术与传统无线通信技术不同,它利用非常宽的频带进行通信,通常超过…...
PiplineADC学习一:
PiplineADC结构: PiplineADC起源之FlashADC PiplineADC起源之Sub-Ranging-ADC 比较器存在失调: 因此每级1bit不实用,需要做冗余位设计。 多比较一次,两个阈值,三个区间,分别对于输出00,01,10。正常2bit应该…...
Linux elasticsearch设置为开机自启动服务
Linux elasticsearch怎么设置为设置为开机自启动服务 1、进入/etc/init.d目录 cd /etc/init.d 2、新建文件elasticsearch,注意,没有扩展名 vi elasticsearch 3、新建文件elasticsearch的内容如下 说明: (1)“su…...
WinForm内嵌Unity3D
Unity3D可以C#脚本进行开,使用vstu2013.msi插件,可以实现在VS2013中的调试。在开发完成后,由于项目需要,需要将Unity3D嵌入到WinForm中。WinForm中的UnityWebPlayer Control可以载入Unity3D。先看效果图。 一、为了能够动态设置ax…...
关于vue中v-for绑定数据重新渲染的问题
我修改被v-for绑定的数据,发现居然不能重新渲染。 查找后得知一下方法: $set 是 Vue 提供的一个全局方法,用于向响应式对象中添加或更新属性,并触发视图更新。它接受三个参数:对象、要添加/更新的属性名或索引,以及新…...
全面解析 Axios 请求库的基本使用方法
Axios 是一个流行的基于 Promise 的 HTTP 请求库,用于在浏览器和 Node.js 中进行 HTTP 请求。它提供了简单易用的 API,可以发送各种类型的请求(如 GET、POST、PUT、DELETE等),并处理响应数据,Axios 在前端工…...
rust踩雷笔记3——生命周期的理解
目录 概念和基本使用一个例子彻底理解最基本的内容 一个例子理解函数签名为什么要有生命周期标注⭐️能不能对编译器蒙混过关? 生命周期是rust中最难的概念——鲁迅 这一块内容即便是看rust圣经,第一遍也有点懵。今天早上二刷突然有了更直观的认识&…...
windows权限维持—黄金白银票据隐藏用户远控RustDeskGotoHttp
windows权限维持—黄金白银票据&隐藏用户&远控&RustDesk&GotoHttp 1. 前置1.1. 初始问题1.1.1. 解决办法 2. 隐藏用户2.1. 工具原理2.2. 案例操作2.2.1. 单机添加用户2.2.1.1. 工具添加用户2.2.1.2. 工具查看隐藏用户2.2.1.3. 本地查看隐藏用户 2.2.2. 域内添加…...
vscode conda activate激活环境出错
vscode conda activate 出错 conda-script.py: error: argument COMMAND: invalid choice: ‘activate’ To initialize your shell, run$ conda init <SHELL_NAME>Currently supported shells are:- bash- fish- tcsh- xonsh- zsh- powershellSee conda init --help f…...
信息与通信工程面试准备——数学知识|正态分布|中心极限定理
目录 正态分布 正态分布的参数 正态分布的第一个参数是均值 正态分布的第二个参数是标准差SD 所有正态分布的共同特征 标准正态分布:正态分布的特例 中心极限定理 理解定义 示例# 1 示例# 2 知道样本均值总是正态分布的实际含义是什么? 正态分…...
Mybatis多表查询与动态SQL的使用
目录 1. Mybatis多表查询 1.1 添加文章表实体类 1.2 文章Interface 1.3 文章.xml 1.4 lombok的toString()有关对象打印的说明 1.5 场景: 一个用户查询多篇文章 2. 复杂情况: 动态SQL的使用 2.1 为什么要使用动态SQL? 2.2 <if>标签 2.3 <trim>标签 2.4 <where&g…...
url 和 uri 有什么区别?
URL(Uniform Resource Locator)和URI(Uniform Resource Identifier)是两个与网络资源定位和标识相关的概念,它们有一些区别,但也存在一些重叠。 URI(Uniform Resource Identifier)是…...
HCIP VLAN实验
VLAN实验 拓扑图配置和分析分析配置LSW1LSW2R1 测试dhcp获取ipICMP测试 拓扑图 配置和分析 分析 从题目来看,因为 pc 1 3都是vlan2而且还是不同网段,pc 2 4 5 6在同一网段,所以可以将pc 1 2 5 4 6分在一个网段 pc4不通5 6 ,那就…...
无涯教程-Perl - waitpid函数
描述 该函数等待ID为PID的子进程终止,返回已故进程的进程ID。如果PID不存在,则返回-1。进程的退出状态包含在$?中。 可以将标志设置为各种值,这些值等于waitpid()UNIX系统调用使用的值。 FLAGS的值为0应该在支持进程的所有操作系统上工作。 语法 以下是此函数的简单语法- …...
Redis之缓存雪崩、缓存击穿、缓存穿透问题
文章目录 前言一、缓存雪崩1.1、原因分析2.2、常用解决方案 二、缓存击穿2.1、原因分析2.2、常用解决方案2.2.1、使用互斥锁2.2.2、逻辑过期方案2.3、方案对比 三、缓存穿透3.1、原因分析3.2、解决方案3.2.1、缓存空对象3.2.3、布隆过滤3.3、方案对比 总结 前言 本文谈谈Redis…...
九五从零开始的运维之路(其三十五)
文章目录 前言一、概述1.概念2.组成3.特点4.工作原理5.优点: 二、各节点及其ip地址三、构建MHA1.ssh免密登录2.构建mysql主从复制(一)安装mariadb数据库并启动(二)master服务器(三)slave服务器&…...
5G科技防汛,助力守护一方平安
“立秋虽已至,炎夏尚还在”,受台风席卷以及季节性影响全国多地正面临强降水的严峻挑战。“落雨又顺秋,绵绵雨不休”,正值“七下八上” 防汛关键时期,贵州省水文水资源局已全面进入备战状态。 为确保及时响应做好防汛抢…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
