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

6、Spring Boot 3.x集成RabbitMQ动态交换机、队列

一、前言

本篇主要是围绕着 Spring Boot 3.x 与 RabbitMQ 的动态配置集成,比如动态新增 RabbitMQ 交换机、队列等操作。

二、默认RabbitMQ中的exchange、queue动态新增及监听

1、新增RabbitMQ配置

RabbitMQConfig.java
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @className: RabbitConfig* @program: chain* @description: RabbitMQ 配置类* @author: kenny* @create: 2024-10-03 21:59* @version: 1.0.0*/
@Configuration
@EnableRabbit
public class RabbitMQConfig {/*** 创建 RabbitTemplate, 用于发送消息** @return RabbitTemplate*/@Beanpublic RabbitTemplate rabbitTemplate() {return new RabbitTemplate();}/*** 创建 RabbitAdmin, 用于创建 Exchange 和 Queue** @param rabbitTemplate RabbitTemplate* @return RabbitAdmin*/@Beanpublic RabbitAdmin rabbitAdmin(RabbitTemplate rabbitTemplate) {return new RabbitAdmin(rabbitTemplate);}
}

2、新增RabbitMQ动态操作组件

RabbitDynamicConfigService.java
RabbitDynamicConfigService.java 中包含了不同类型Exchange的创建、删除,Queue的创建和删除、绑定Exchange
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Map;/*** @className: RabbitDynamicConfigService* @program: chain* @description: 动态创建队列和交换机* @author: kenny* @create: 2024-10-03 23:49* @version: 1.0.0*/
@Slf4j
@Service
public class RabbitDynamicConfigService {/*** 为了解决循环依赖问题*/private final RabbitAdmin rabbitAdmin;private final RabbitListenerService rabbitListenerService;@Autowiredpublic RabbitDynamicConfigService(RabbitAdmin rabbitAdmin,RabbitListenerService rabbitListenerService) {this.rabbitAdmin = rabbitAdmin;this.rabbitListenerService = rabbitListenerService;}/*** 动态创建队列,并持久化** @param queueName 队列名称*/public void createQueue(String queueName) {// 队列持久化Queue queue = new Queue(queueName, true);// 创建队列rabbitAdmin.declareQueue(queue);System.out.println("队列创建成功: " + queueName);}/*** 动态创建队列,并持久化** @param queueName 队列名称*/public void createQueue(String queueName, Boolean isListener) {// 队列持久化Queue queue = new Queue(queueName, true);// 创建队列rabbitAdmin.declareQueue(queue);System.out.println("队列创建成功: " + queueName);if (!isListener) {return;}rabbitListenerService.createListener(queueName);}/*** 动态创建交换机,并持久化** @param exchangeName 交换机名称*/public void createExchange(String exchangeName) {// 交换机持久化DirectExchange exchange = new DirectExchange(exchangeName, true, false);rabbitAdmin.declareExchange(exchange);log.info("交换机创建成功: {}", exchangeName);}// 动态创建 Fanout 交换机public void createDirectExchange(String exchangeName) {DirectExchange fanoutExchange = new DirectExchange(exchangeName, true, false); // 持久化rabbitAdmin.declareExchange(fanoutExchange);log.info("Direct 交换机创建成功: {}", exchangeName);}// 动态创建 Fanout 交换机public void createFanoutExchange(String exchangeName) {FanoutExchange fanoutExchange = new FanoutExchange(exchangeName, true, false); // 持久化rabbitAdmin.declareExchange(fanoutExchange);log.info("Fanout 交换机创建成功: {}", exchangeName);}// 动态创建 Topic 交换机public void createTopicExchange(String exchangeName) {TopicExchange topicExchange = new TopicExchange(exchangeName, true, false); // 持久化rabbitAdmin.declareExchange(topicExchange);log.info("Topic 交换机创建成功: {}", exchangeName);}// 动态创建 Headers 交换机public void createHeadersExchange(String exchangeName) {HeadersExchange headersExchange = new HeadersExchange(exchangeName, true, false); // 持久化rabbitAdmin.declareExchange(headersExchange);log.info("Headers 交换机创建成功: {}", exchangeName);}/*** 动态绑定队列到交换机,并指定路由键** @param queueName    队列名称* @param exchangeName 交换机名称* @param routingKey   路由键*/public void bindQueueToExchange(String queueName, String exchangeName, String routingKey) {Queue queue = new Queue(queueName);DirectExchange exchange = new DirectExchange(exchangeName);Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);rabbitAdmin.declareBinding(binding);log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);}/*** 动态绑定队列到交换机,并指定路由键** @param queueName    队列名称* @param exchangeName 交换机名称* @param routingKey   路由键*/public void moreExchangeTypeBindQueueToExchange(String queueName, String exchangeType, String exchangeName, String routingKey, Map<String, Object> headers) {switch (exchangeType) {case "fanout" -> bindQueueToExchange(queueName, exchangeName, routingKey);case "direct" -> bindQueueToDirectExchange(queueName, exchangeName, routingKey);case "topic" -> bindQueueToTopicExchange(queueName, exchangeName, routingKey);case "headers" -> bindQueueToHeadersExchange(queueName, exchangeName, headers);default -> throw new IllegalArgumentException("不支持的交换机类型: " + exchangeType);}}/*** 动态绑定队列到交换机,并指定路由键(exchange: direct)** @param queueName    队列名称* @param exchangeName 交换机名称*/public void bindQueueToFanoutExchange(String queueName, String exchangeName) {Queue queue = new Queue(queueName);FanoutExchange exchange = new FanoutExchange(exchangeName);Binding binding = BindingBuilder.bind(queue).to(exchange);rabbitAdmin.declareBinding(binding);log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName);}/*** 动态绑定队列到交换机,并指定路由键(exchange: direct)** @param queueName    队列名称* @param exchangeName 交换机名称* @param routingKey   路由键*/public void bindQueueToDirectExchange(String queueName, String exchangeName, String routingKey) {Queue queue = new Queue(queueName);DirectExchange exchange = new DirectExchange(exchangeName);Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);rabbitAdmin.declareBinding(binding);log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);}/*** 动态绑定队列到交换机,并指定路由键(exchange: topic)** @param queueName    队列名称* @param exchangeName 交换机名称* @param routingKey   路由键*/public void bindQueueToTopicExchange(String queueName, String exchangeName, String routingKey) {Queue queue = new Queue(queueName);TopicExchange exchange = new TopicExchange(exchangeName);Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);rabbitAdmin.declareBinding(binding);log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);}/*** 动态绑定队列到交换机,并指定路由键(exchange: headers)** @param queueName    队列名称* @param exchangeName 交换机名称* @param headers      路由键*/public void bindQueueToHeadersExchange(String queueName, String exchangeName, Map<String, Object> headers) {Queue queue = new Queue(queueName);HeadersExchange exchange = new HeadersExchange(exchangeName);Binding binding = BindingBuilder.bind(queue).to(exchange).whereAll(headers).match();rabbitAdmin.declareBinding(binding);log.info("队列 {}", queueName + " 已绑定到 Headers 交换机 {}", exchangeName + ",使用头部匹配规则: {}", headers);}/*** 动态删除队列** @param queueName 队列名称*/public void deleteQueue(String queueName) {rabbitAdmin.deleteQueue(queueName);log.info("队列删除成功: {}", queueName);}/*** 动态删除交换机** @param exchangeName 交换机名称*/public void deleteExchange(String exchangeName) {rabbitAdmin.deleteExchange(exchangeName);log.info("交换机删除成功: {}", exchangeName);}
}

3、RabbitMQ中队列的动态监听

RabbitListenerService.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @className: RabbitListenerService* @program: chain* @description: RabbitMQ监听器Service组件* @author: kenny* @create: 2024-10-04 01:40* @version: 1.0.0*/
@Slf4j
@Service
public class RabbitListenerService {// 为了解决循环依赖问题private final SimpleRabbitListenerContainerFactory listenerContainerFactory;private final ConnectionFactory connectionFactory;@Autowiredpublic RabbitListenerService(SimpleRabbitListenerContainerFactory listenerContainerFactory,ConnectionFactory connectionFactory) {this.listenerContainerFactory = listenerContainerFactory;this.connectionFactory = connectionFactory;}/*** 创建监听器容器并启动监听** @param queueName 队列名称*/public void createListener(String queueName) {// 创建并启动监听器容器SimpleMessageListenerContainer container = listenerContainerFactory.createListenerContainer();container.setConnectionFactory(connectionFactory);container.setQueueNames(queueName);// 监听逻辑处理container.setMessageListener(new MessageListenerAdapter(new Object() {public void handleMessage(String message) {System.out.println("收到来自RabbitMQ中队列:" + queueName + " 队列的消息:" + message);}}));// 启动监听器容器container.start();System.out.println("RabbitMQ队列监听器已启动:" + queueName);}
}

4、RabbitMQ中的Exchange、Queue动态操作接口

RabbitDynamicChannelController.java
import com.chain.air.rpp.exchange.rabbit.RabbitDynamicConfigService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;/*** @className: RabbitDynamicController* @program: chain* @description: RabbitMQ 动态创建队列、交换机,绑定等操作* @author: kenny* @create: 2024-10-04 00:22* @version: 1.0.0*/
@RestController
@RequestMapping("/rabbit/dynamic/channel")
public class RabbitDynamicChannelController {/*** 动态创建队列和交换机*/@Resourceprivate RabbitDynamicConfigService rabbitDynamicConfigService;/*** 动态创建队列** @param queueName 队列名称* @return 处理结果*/@GetMapping("/createQueue")public String createQueue(@RequestParam("queueName") String queueName) {rabbitDynamicConfigService.createQueue(queueName);return "队列已创建: " + queueName;}/*** 动态创建交换机** @param exchangeName 交换机名称* @return 处理结果*/@GetMapping("/createExchange")public String createExchange(@RequestParam("exchangeName") String exchangeName) {rabbitDynamicConfigService.createExchange(exchangeName);return "交换机已创建: " + exchangeName;}/*** 动态绑定队列和交换机** @param queueName    队列名称* @param exchangeName 交换机名称* @param routingKey   路由键* @return 处理结果*/@GetMapping("/bindQueue")public String bindQueueToExchange(@RequestParam("queueName") String queueName,@RequestParam("exchangeName") String exchangeName,@RequestParam("routingKey") String routingKey) {rabbitDynamicConfigService.bindQueueToExchange(queueName, exchangeName, routingKey);return "队列和交换机已绑定: " + queueName + " -> " + exchangeName;}/*** 动态删除队列** @param queueName 队列名称* @return 处理结果*/@GetMapping("/deleteQueue")public String deleteQueue(@RequestParam("queueName") String queueName) {rabbitDynamicConfigService.deleteQueue(queueName);return "队列已删除: " + queueName;}/*** 动态删除交换机** @param exchangeName 交换机名称* @return 处理结果*/@GetMapping("/deleteExchange")public String deleteExchange(@RequestParam("exchangeName") String exchangeName) {rabbitDynamicConfigService.deleteExchange(exchangeName);return "交换机已删除: " + exchangeName;}// 创建并绑定 Fanout 交换机@GetMapping("/createDirectExchange")public String createDirectExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam String routingKey) {rabbitDynamicConfigService.createDirectExchange(exchangeName);rabbitDynamicConfigService.bindQueueToDirectExchange(queueName, exchangeName, routingKey);return "Fanout Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with routing key: " + routingKey;}// 创建并绑定 Fanout 交换机@GetMapping("/createFanoutExchange")public String createFanoutExchange(@RequestParam String exchangeName, @RequestParam String queueName) {rabbitDynamicConfigService.createFanoutExchange(exchangeName);rabbitDynamicConfigService.bindQueueToFanoutExchange(queueName, exchangeName);return "Fanout Exchange and Queue Binding created: " + exchangeName + " -> " + queueName;}// 创建并绑定 Topic 交换机@GetMapping("/createTopicExchange")public String createTopicExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam String routingKey) {rabbitDynamicConfigService.createTopicExchange(exchangeName);rabbitDynamicConfigService.bindQueueToTopicExchange(queueName, exchangeName, routingKey);return "Topic Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with routing key: " + routingKey;}// 创建并绑定 Headers 交换机@GetMapping("/createHeadersExchange")public String createHeadersExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam Map<String, String> headersMap) {Map<String, Object> headers = new HashMap<>(headersMap);rabbitDynamicConfigService.createHeadersExchange(exchangeName);rabbitDynamicConfigService.bindQueueToHeadersExchange(queueName, exchangeName, headers);return "Headers Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with headers: " + headers;}
}

5、RabbitMQ中的Queue消息监听动态操作接口

RabbitChannelListenerController.java
import com.chain.air.rpp.exchange.rabbit.RabbitDynamicConfigService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @className: RabbitListenerController* @program: chain* @description: RabbitMQ 监听器 Controller 组件* @author: kenny* @create: 2024-10-04 01:30* @version: 1.0.0*/
@RestController
@RequestMapping("/rabbit/channel/listener")
public class RabbitChannelListenerController {@Resourceprivate RabbitDynamicConfigService rabbitDynamicConfigService;/*** 创建监听器,监听指定队列** @param queueName 队列名称* @return 处理结果*/@GetMapping("/queue")public String listenQueue(@RequestParam("queueName") String queueName) {rabbitDynamicConfigService.createQueue(queueName, true);return "开始监听队列:" + queueName;}
}

三、动态exchange、queue的测试

1、测试Exchange、Queue的动态创建和删除

2、测试Exchange和Queue的动态绑定

3、发送、接收消息测试动态创建Exchange、Queue

4、测试Queue的动态监听接口

下一篇:7、Spring Boot 3.x集成RabbitMQ动态实例等操作

相关文章:

6、Spring Boot 3.x集成RabbitMQ动态交换机、队列

一、前言 本篇主要是围绕着 Spring Boot 3.x 与 RabbitMQ 的动态配置集成&#xff0c;比如动态新增 RabbitMQ 交换机、队列等操作。二、默认RabbitMQ中的exchange、queue动态新增及监听 1、新增RabbitMQ配置 RabbitMQConfig.java import org.springframework.amqp.rabbit.a…...

【分布式微服务云原生】 探索SOAP协议:简单对象访问协议的深度解析与实践

探索SOAP协议&#xff1a;简单对象访问协议的深度解析与实践 摘要&#xff1a; 在现代分布式系统中&#xff0c;SOAP&#xff08;简单对象访问协议&#xff09;扮演着至关重要的角色&#xff0c;提供了一种标准化的方式来实现不同系统间的通信。本文深入探讨了SOAP的工作原理、…...

C语言题目练习2

前面我们知道了单链表的结构及其一些数据操作&#xff0c;今天我们来看看有关于单链表的题目~ 移除链表元素 移除链表元素&#xff1a; https://leetcode.cn/problems/remove-linked-list-elements/description/ 这个题目要求我们删除链表中是指定数据的结点&#xff0c;最终返…...

复变函数与积分变换——留数定理求拉氏逆变换

1.留数定理 若s1&#xff0c;s2&#xff0c;…&#xff0c;sn是F(s)的所有奇点&#xff08;函数在某个点上的取值无定义或者无限大&#xff09;&#xff0c;且当s→∞时&#xff0c;F(s)→0&#xff0c;则有&#xff1a; 一般地&#xff1a; s1是一级极点&#xff0c;则&#…...

RabbitMQ事务模块

目录 消息分发​​​​​​​ 负载均衡 幂等性保障 顺序性保障 顺序性保障方案 二号策略:分区消费 三号策略:消息确认机制 四号策略: 消息积压 RabbitMQ集群 选举过程 RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制&#xff0c;要么全部成功&#xff0c;要么全…...

Android终端GB28181音视频实时回传设计探讨

技术背景 好多开发者&#xff0c;在调研Android平台GB28181实时回传的时候&#xff0c;对这块整体的流程&#xff0c;没有个整体的了解&#xff0c;本文以大牛直播SDK的SmartGBD设计开发为例&#xff0c;聊下如何在Android终端实现GB28181音视频数据实时回传。 技术实现 Andr…...

AI金融攻防赛:金融场景凭证篡改检测(DataWhale组队学习)

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月学习赛的AI金融攻防赛学习总结文档。本文主要讲解如何解决 金融场景凭证篡改检测的核心问题&#xff0c;以及解决思路和代码实现过程。希望…...

华为OD机试真题---喊7的次数重排

题目描述 喊7是一个传统的聚会游戏。N个人围成一圈&#xff0c;按顺时针从1到N编号。编号为1的人从1开始喊数&#xff0c;下一个人喊的数字为上一个人的数字加1。但是&#xff0c;当将要喊出来的数字是7的倍数或者数字本身含有7时&#xff0c;不能把这个数字直接喊出来&#x…...

使用阿里巴巴的图

参考链接1 引用彩色图标可参考以下链接 &#xff08;到第三步 测试图标效果 的时候 还是可以保持之前的写法&#xff1a;<i/sapn class“iconfont icon-xxx”>也会出现彩色的&#xff09; 参考链接2 阿里巴巴字体使用 也可以直接将官网的代码复制过来到页面的css区域...

【hot100-java】排序链表

链表题。 使用归并排序法。 一图解决。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; thi…...

腾讯云视立方TRTCCalling Web 相关

基础问题 什么是 TRTCCalling&#xff1f; TRTCCalling 是在 TRTC 和 TIM 的基础上诞生的一款快速集成的音视频的解决方案。支持1v1和多人视频/语音通话。 TRTCCalling 是否支持接受 roomID 为字符串? roomID 可以 string&#xff0c;但只限于数字字符串。 环境问题 Web …...

使用argparse库实现命令行参数解析的实用指南

使用argparse库实现命令行参数解析的实用指南 在现代软件开发中,命令行工具的使用越来越普遍。无论是自动化脚本、数据处理工具,还是系统管理工具,命令行参数解析都是一个不可或缺的功能。Python的argparse库提供了一种简单而强大的方式来处理命令行参数,使得开发者能够轻…...

kafka消息队列核心内容及常见问题

目录 1. 使用消息队列的目的&#xff08;优点与缺点&#xff09; 2. 常见各消息队列对比 3. kafka介绍 3.1 kafka简介 3.2 kafka特点 3.3 kafka系统架构 3.4 设置数据可靠性 3.4.1 Topic 分区副本 3.4.2 消息确认机制 4. 常见问题&#xff08;面试题&#xff09; 4.…...

电脑无线网wifi和有线网同时使用(内网+外网同时使用)

一、要求 我这里以无线网wifi为外网&#xff0c;有线网卡为内网为例&#xff1a; 一、基本信息 无线wifi&#xff08;外网&#xff09;&#xff1a;ip是192.168.179.235&#xff0c;网关是192.168.179.95有线网&#xff08;内网&#xff09;&#xff1a;ip是192.168.10.25&…...

Ubuntu22.04阿里云服务器 Gitlab搭建CICD

gitlab搭建cicd流水线教程 1、阿里云申请免费云盘 申请免费云盘用于创建gitlab 申请方法百度 2、安装gitlab-ce 更新系统&#xff1a; sudo apt update sudo apt upgrade -y 安装必要的依赖&#xff1a; sudo apt install -y curl openssh-server ca-certificates pos…...

2024最新全流程ChatGPT深度科研应用、论文与项目撰写、数据分析、机器学习、深度学习及AI绘图

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。 2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其…...

网络流C++

网络流问题及其应用 网络流问题是图论中的一个经典问题&#xff0c;应用于交通调度、物流配送、计算机网络等领域。它通过模型化图中的流量传递过程&#xff0c;解决从源点传递流量到汇点的最优流量分配问题。本文将介绍网络流的基本概念、几种经典算法&#xff0c;并通过一个…...

RTC -

RTC 目录 RTC 回顾 RTC 如何实现RTC制作一个时钟日历 代码编写 rtc.c完整代码 模块开发的步骤&#xff1a; 1、找文档 2、 在文档里面找通信方式&#xff0c;通信过程&#xff08;协议&#xff09; 3、代码> -- 前面学的是模块的开发&#xff0c;串口类&#xff0c;I…...

图像处理中常用的统计矩

目录 原点矩中心矩常用的统计矩偏度&#xff08;Skewness&#xff09;定义解释 峰度&#xff08;Kurtosis&#xff09;定义解释 统计矩的应用MATLAB相关函数 原点矩&#xff08;Moment about the Origin&#xff09;和中心矩&#xff08;Central Moment&#xff09;是概率论和数…...

Ubuntu 详解| Ubuntu ssh| Ubuntu apt命令大全| Ubuntu性能优化| Ubuntu换镜像源

Ubuntu 是Debian开源linux系统体系下的子分支之一 Debian-ubuntu 和它一样的还有 kali&#xff08;一款渗透测试软件&#xff09; Debian-kali 小白参考 &#xff1a;Centos 7.9 安装 图解版 小白必看 最新_centos7.9-CSDN博客文章浏览阅读2.5k次&#xff0c;点赞…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...