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

SpringBoot 项目中使用 spring-boot-starter-amqp 依赖实现 RabbitMQ

文章目录

    • 前言
    • 1、application.yml
    • 2、RabbitMqConfig
    • 3、MqMessage
    • 4、MqMessageItem
    • 5、DirectMode
    • 6、StateConsumer:消费者
    • 7、InfoConsumer:消费者

前言

本文是工作之余的随手记,记录在工作期间使用 RabbitMQ 的笔记。

1、application.yml

  • 使用 use 属性,方便随时打开和关闭使用 MQ ,并且可以做到细化控制。
spring:rabbitmq:use: truehost: 10.100.10.100port: 5672username: wenpassword: 123456exchangeSubPush: 'exWen'queueSubPush: 'ha.queue.SubPush'routeSubPush: '1000'exchangeState: sync.ex.StatequeueState: ha.q.ServerqueueStateSync: ha.q.StateServerrouteState: stateexchangeOnlineMonitor: 'sync.ex.State'routeOnlineMonitor: 'state'queueOnlineMonitor: 'ha.q.Online'
  • pom.xml 文件中使用的是 SpringBoot 项目,使用 spring-boot-starter-amqp 依赖。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.wen</groupId><artifactId>springboot-mybatis</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.5.3</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.18</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version></dependency></dependencies>
</project>

2、RabbitMqConfig

  • 配置类,将可配置的参数使用 @Value 做好配置,与 application.yml 相互对应。
package com.wen.mq;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;@Slf4j
@Configuration
@Data
public class RabbitMqConfig {@Value("${spring.rabbitmq.use:true}")private boolean use;@Value("${spring.rabbitmq.host}")private String host;@Value("${spring.rabbitmq.port}")private int port;@Value("${spring.rabbitmq.username}")private String username;@Value("${spring.rabbitmq.password}")private String password;@Value("${spring.rabbitmq.virtual-host:}")private String virtualHost;@Value("${spring.rabbitmq.exchangeState}")private String exchangeState;@Value("${spring.rabbitmq.queueState}")private String queueState;@Value("${spring.rabbitmq.routeState}")private String routeState;@Value(("${spring.rabbitmq.queueStateSync}"))private String queueStateSync;@Value("${spring.rabbitmq.exchangeOnlineInfo}")private String exchangeOnlineInfo;@Value("${spring.rabbitmq.routeOnlineInfo}")private String routeOnlineInfo;@Value("${spring.rabbitmq.queueOnlineInfo}")private String queueOnlineInfo;@PostConstructprivate void init() {}
}

3、MqMessage

  • MQ 消息实体类
package com.wen.mq;import lombok.Data;@Data
public class MqMessage<T> {private String msgType;private String msgOrigin;private long time;private T data;}

4、MqMessageItem

  • MQ 消息实体类
package com.wen.mq;import lombok.Data;@Data
public class MqMessageItem {private long userId;private String userName;private int userAge;private String userSex;private String userPhone;private String op;}

5、DirectMode

  • 配置中心:使用 SimpleMessageListenerContainer 进行配置。
  • 新加一个消费者队列就要在这里进行配置。
package com.wen.mq;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Slf4j
@Configuration
public class DirectMode {@AutowiredRabbitMqConfig rabbitMqConfig;@Autowiredprivate CachingConnectionFactory connectionFactory;@Autowiredprivate StateConsumer stateConsumer;@Autowiredprivate InfoConsumer infoConsumer;@Beanpublic SimpleMessageListenerContainer initMQ() {if (!rabbitMqConfig.isUse()) {return null;}log.info("begin!");SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);container.setConcurrentConsumers(1);container.setMaxConcurrentConsumers(1);container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认// 设置一个队列container.setQueueNames(rabbitMqConfig.getQueueStateSync());//如果同时设置多个队列如下: 前提是队列都是必须已经创建存在的//container.setQueueNames("TestDirectQueue","TestDirectQueue2","TestDirectQueue3”);//另一种设置队列的方法,如果使用这种情况,那么要设置多个,就使用addQueues//container.setQueues(new Queue("TestDirectQueue",true));//container.addQueues(new Queue("TestDirectQueue2",true));//container.addQueues(new Queue("TestDirectQueue3",true));container.setMessageListener(stateConsumer);log.info("end");return container;}@Beanpublic SimpleMessageListenerContainer contactSyncContainer() {if (!rabbitMqConfig.isUse()) {return null;}log.info("contact begin");SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);container.setConcurrentConsumers(1);container.setMaxConcurrentConsumers(1);container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息//设置一个队列container.setQueueNames(rabbitMqConfig.getQueueOnlineInfo());container.setMessageListener(infoConsumer);log.info("contact end");return container;}@Beanpublic Queue queueState() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueState());}@Beanpublic Queue queueStateSync() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueStateSync());}@BeanDirectExchange exchangeState() {if (!rabbitMqConfig.isUse()) {return null;}return new DirectExchange(rabbitMqConfig.getExchangeState());}@BeanBinding bindingState() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueState()).to(exchangeState()).with(rabbitMqConfig.getRouteState());}@BeanBinding bindingStateSync() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueStateSync()).to(exchangeState()).with(rabbitMqConfig.getRouteState());}// 新加一个消费者@Beanpublic Queue queueOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return new Queue(rabbitMqConfig.getQueueOnlineInfo());}@BeanDirectExchange exchangeOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return new DirectExchange(rabbitMqConfig.getExchangeOnlineInfo());}@BeanBinding bindingExchangeOnlineMonitor() {if (!rabbitMqConfig.isUse()) {return null;}return BindingBuilder.bind(queueOnlineMonitor()).to(exchangeOnlineMonitor()).with(rabbitMqConfig.getRouteOnlineInfo());}
}

6、StateConsumer:消费者

  • 实现 ChannelAwareMessageListener 接口,可以在这里面做相应的操作,例如存缓存,存库等。
package com.wen.mq;import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;@Slf4j
@Component
public class StateConsumer implements ChannelAwareMessageListener {@AutowiredRabbitMqConfig rabbitMqConfig;@Overridepublic void onMessage(Message message, Channel channel) throws Exception {String queueName = message.getMessageProperties().getConsumerQueue();long deliveryTag = message.getMessageProperties().getDeliveryTag();if (!rabbitMqConfig.getQueueStateSync().equals(queueName)) {String bodyStr = new String(message.getBody(), StandardCharsets.UTF_8);try {MqMessage<List<MqMessageItem>> mqMessage = JSON.parseObject(bodyStr, new TypeReference<MqMessage<List<MqMessageItem>>>() {});// 这里可以对消息做其他处理,例如存储到缓存中List<MqMessageItem> items = mqMessage.getData();if (CollectionUtil.isNotEmpty(items)) {applyToRedis(mqMessage);}log.info("consume mq msg ok, queue:{}, deliveryTag:{}, msg:{}", queueName, deliveryTag, mqMessage);channel.basicAck(deliveryTag, false);} catch (JSONException e) {log.error("parse mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, false);} catch (Exception e) {log.error("consume mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, true); //为true会重新放回队列}}}public static final String MQ_STATE_OP_REMOVE_STATE = "REMOVE_STATE";public static final String MQ_STATE_OP_CHANGE_STATE = "CHANGE_STATE";private void applyToRedis(MqMessage<List<MqMessageItem>> mqMessage) {List<MqMessageItem> data = mqMessage.getData();Map<String, List<MqMessageItem>> itemGroupByOp = data.stream().collect(Collectors.groupingBy(item -> item.getOp()));List<MqMessageItem> stateToRemove = itemGroupByOp.get(MQ_STATE_OP_REMOVE_STATE);List<MqMessageItem> stateToChange = itemGroupByOp.get(MQ_STATE_OP_CHANGE_STATE);if (CollectionUtil.isNotEmpty(stateToRemove)) {Map<Long, Set<String>> map = new HashMap<>();for (MqMessageItem item : stateToRemove) {map.computeIfAbsent(item.getUserId(), u -> new HashSet<>()).add(String.valueOf(item.getUserAge()));}// cacheService.removeUserState(map);}if (CollectionUtil.isNotEmpty(stateToChange)) {List<MqMessageItem> list = stateToChange.stream().map(u -> {MqMessageItem dto = new MqMessageItem();dto.setUserId(u.getUserId());dto.setUserAge(u.getUserAge());dto.setUserName(u.getUserName());dto.setUserSex(u.getUserSex());dto.setUserPhone(u.getUserPhone());return dto;}).collect(Collectors.toList());// cacheService.saveUserState(list);}}
}

7、InfoConsumer:消费者

  • 实现 ChannelAwareMessageListener 接口,可以在这里面做相应的操作,例如存缓存,存库等。
package com.wen.mq;import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class InfoConsumer implements ChannelAwareMessageListener {@AutowiredRabbitMqConfig rabbitMqConfig;@Overridepublic void onMessage(Message message, Channel channel) throws Exception {String queueName = message.getMessageProperties().getConsumerQueue();log.info("queueName: {}", queueName);long deliveryTag = message.getMessageProperties().getDeliveryTag();try {byte[] body = message.getBody();String content = new String(body);MqMessage msg = JSONObject.parseObject(content, MqMessage.class);if (rabbitMqConfig.getQueueOnlineInfo().equals(queueName)) {// 订阅到的消息就是变更的消息// 这里可使用service对消息进行消费,返回一个booleanlog.info("用户监控数据写入失败!数据:{}", msg);}log.info("consume mq msg ok, queue:{}, deliveryTag:{}, msg:{}", queueName, deliveryTag, msg);channel.basicAck(deliveryTag, false);} catch (JSONException e) {log.error("parse mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, false); //为true会重新放回队列} catch (Exception e) {log.error("consume mq msg exception, queue:{}, deliveryTag:{}", queueName, deliveryTag, e);channel.basicReject(deliveryTag, true); //为true会重新放回队列}}
}

相关文章:

SpringBoot 项目中使用 spring-boot-starter-amqp 依赖实现 RabbitMQ

文章目录 前言1、application.yml2、RabbitMqConfig3、MqMessage4、MqMessageItem5、DirectMode6、StateConsumer&#xff1a;消费者7、InfoConsumer&#xff1a;消费者 前言 本文是工作之余的随手记&#xff0c;记录在工作期间使用 RabbitMQ 的笔记。 1、application.yml 使…...

Uniapp 安装安卓、IOS模拟器并调试

一、安装Android模拟器并调试 1. 下载并安装 Android Studio 首先下载 Mac 环境下的 Android Studio 的安装包&#xff0c;为dmg 格式。 下载完将Android Studio 向右拖拽到Applications中&#xff0c;接下来等待安装完成就OK啦&#xff01; 打开过程界面如下图所示&#xf…...

JavaScript 中的原型和原型链

JavaScript 中的原型和原型链也是一个相对较难理解透彻的知识点&#xff0c;下面结合详细例子来进行说明&#xff1a; 一、原型的概念 在 JavaScript 中&#xff0c;每个函数都有一个 prototype 属性&#xff0c;这个属性指向一个对象&#xff0c;这个对象就是所谓的 “原型对…...

数组变换(两倍)

数组变换 以最大元素为基准元素&#xff0c;判读其他元素能否通过 x 2 成为最大值&#xff01; 那么怎么判断呢&#xff1a; max % arr[i] 0arr[i] * 2 ^n max int x 2 ^ n max / arr[i] 3.只需判断 这个 x 是不是 2 的 n 次放就可以了&#xff01; 判断 是否为 2 的 n 次 …...

GBN协议、SR协议

1、回退N步&#xff08;Go-Back-N,GBN&#xff09;协议&#xff1a; 总结&#xff1a; GBN协议的特点&#xff1a; &#xff08;1&#xff09;累计确认机制&#xff1a;当发送方收到ACKn时&#xff0c;表明接收方已正确接收序号为n以及序号小于n的所有分组&#xff0c;发送窗…...

三维扫描检测仪3d扫描测量尺寸-自动蓝光测量

在现代工业及生产过程中&#xff0c;精确、高效的尺寸检测是保证产品质量、提升生产效率的关键因素。 红、蓝光测量&#xff0c;以其高精度、高效率和非接触式的特点&#xff0c;在工业及生产中发挥着越来越重要的作用。蓝光测量技术利用蓝色激光光源&#xff0c;通过扫描被测…...

大模型翻译能力评测

1. 背景介绍 随着自然语言处理技术的飞速发展&#xff0c;机器翻译已经成为一个重要的研究领域。近年来&#xff0c;基于大模型的语言模型在机器翻译任务上取得了显著的进展。这些大模型通常具有数亿甚至数千亿的参数&#xff0c;能够更好地理解和生成自然语言。 但是&#xf…...

MySQL隐式转换造成索引失效

一、什么是 MySQL 的隐式转换&#xff1f; MySQL 在执行查询语句时&#xff0c;有时候会自动帮我们进行数据类型的转换&#xff0c;这个过程就是隐式转换。比如说&#xff0c;我们在一个 INT 类型的字段上进行查询&#xff0c;但是传入的查询条件却是字符串类型的值&#xff0c…...

SuperMap Objects组件式GIS开发技术浅析

引言 随着GIS应用领域的扩展&#xff0c;GIS开发工作日显重要。一般地&#xff0c;从平台和模式上划分&#xff0c;GIS二次开发主要有三种实现方式&#xff1a;独立开发、单纯二次开发和集成二次开发。上述的GIS应用开发方式各有利弊&#xff0c;其中集成二次开发既可以充分利…...

多组数输入a+b:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 输入描述: 输入包含多组数据&#xff0c;每组数据输入一行&#xff0c;包含两个整数 输出描述: 对于每组数据输出一行包含一个整数表示两个整数的和 代码: import java.util.Scanner; pu…...

R语言结构方程模型(SEM)在生态学领域中的应用

目录 专题一、R/Rstudio简介及入门 专题二、结构方程模型&#xff08;SEM&#xff09;介绍 专题三&#xff1a;R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 专题四&#xff1a;SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 专题五&#xff1…...

架构-微服务-服务调用Dubbo

文章目录 前言一、Dubbo介绍1. 什么是Dubbo 二、实现1. 提供统一业务api2. 提供服务提供者3. 提供服务消费者 前言 服务调用方案--Dubbo‌ 基于 Java 的高性能 RPC分布式服务框架&#xff0c;致力于提供高性能和透明化的 RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。…...

【SpringBoot问题】IDEA中用Service窗口展示所有服务及端口的办法

1、调出Service窗口 打开View→Tool Windows→Service&#xff0c;即可显示。 2、正常情况应该已经出现SpringBoot&#xff0c;如下图请继续第三步 3、配置Service窗口的项目启动类型。微服务一般是Springboot类型。所以这里需要选择一下。 点击最后一个号&#xff0c;点击Ru…...

OpenCV 图像轮廓查找与绘制全攻略:从函数使用到实战应用详解

摘要&#xff1a;本文详细介绍了 OpenCV 中用于查找图像轮廓的 cv2.findContours() 函数以及绘制轮廓的 cv2.drawContours() 函数的使用方法。涵盖 cv2.findContours() 各参数&#xff08;如 mode 不同取值对应不同轮廓检索模式&#xff09;及返回值的详细解析&#xff0c;搭配…...

电机驱动MCU介绍

电机驱动MCU是一种专为电机控制设计的微控制器单元&#xff0c;它集成了先进的控制算法和高性能的功率输出能力。 电机驱动MCU采用高性能的处理器核心&#xff0c;具有快速的运算速度和丰富的外设接口。它内置了专业的电机控制算法&#xff0c;包括PID控制、FOC&#xff08;Fi…...

人工智能学习框架详解及代码使用案例

人工智能学习框架详解及代码使用案例 人工智能(AI)学习框架是构建和训练AI模型的基础工具,它们提供了一组预定义的算法、函数和工具,使得开发者能够更快速、更高效地构建AI应用。本文将深入探讨人工智能学习框架的基本概念、分类、优缺点、选择要素以及实际应用,并通过代…...

修改Textview中第一个字的字体,避免某些机型人民币¥不显示

在 Android 中&#xff0c;系统提供了三种常用的字体类型&#xff0c;分别是&#xff1a; Serif&#xff08;衬线字体&#xff09;: 这种字体有明显的衬线或笔画末端装饰&#xff0c;通常用于印刷品和书籍&#xff0c;给人一种正式和优雅的感觉。示例&#xff1a;Typeface.SERI…...

彻底理解quadtree四叉树、Octree八叉树 —— 点云的空间划分的标准做法

1.参考文章&#xff1a; &#xff08;1&#xff09;https://www.zhihu.com/question/25111128 这里面的第一个回答&#xff0c;有一幅图&#xff1a; 只要理解的四叉树的构建&#xff0c;对于八叉树的构建原理类比方法完全一样&#xff1a;对于二维平面内的随机分布的这些点&…...

Python时间序列优化之道滑动与累积窗口的应用技巧

大家好&#xff0c;在时间序列数据处理中&#xff0c;通常会进行滑动窗口计算(rolling)和累积窗口计算(expanding)等操作&#xff0c;以便分析时间序列的变化趋势或累积特征。Pandas提供的rolling和expanding函数提供了简单、高效的实现方式&#xff0c;特别适用于金融、气象、…...

Buffered 和 BuffWrite

Buffered和BuffWrite是Java IO包中的两个类&#xff0c;用于提高IO操作的效率。 Buffered是一个缓冲区类&#xff0c;可以将一个InputStream或者一个Reader包装起来&#xff0c;提供了一定的缓冲区大小&#xff0c;可以一次读取多个字节或字符&#xff0c;减少了读取的次数&am…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...