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

微服务框架SpringcloudAlibaba+Nacos集成RabbitMQ

目前公司使用jeepluscloud版本,这个版本没有集成消息队列,这里记录一下,集成的过程;这个框架跟ruoyi的那个微服务版本结构一模一样,所以也可以快速上手。

1.项目结构图:

配置类的东西做成一个公共的模块

在这里插入图片描述

rabbitmq模块:

在这里插入图片描述

2.核心配置

1.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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>jeeplus-common</artifactId><groupId>org.jeeplus</groupId><version>${revision}</version></parent><modelVersion>4.0.0</modelVersion><artifactId>jeeplus-common-rabbitmq</artifactId><packaging>jar</packaging><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.jeeplus</groupId><artifactId>jeeplus-common-core</artifactId><version>${project.parent.version}</version></dependency></dependencies>
</project>

2.ConditionalOnRabbit

package com.jeeplus.common.rabbit.conditional;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;/*** 判断系统是否在启用了Rabbit, 未启用的情况下不将Bean注册到系统中** 使用场景: 在不使用Rabbit中间件但未去除Rabbit依赖的情况下, 通过配置文件中关闭Rabbit选项,* 同时将这个注解到有`@RabbitListener`标志的类上,让这个对象不注册到Spring容器中,* 从而避免`RabbitMQ`进行无限尝试重连服务器,导致项目一直抛出异常,影响开发和使用。** @author xxm* @since 2022/12/12*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRabbitEnable.class)
public @interface ConditionalOnRabbit {}

3.OnRabbitEnable

package com.jeeplus.common.rabbit.conditional;import com.jeeplus.common.rabbit.configuration.RabbitMqProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;/*** 判断是否在启用了Rabbit, 用来控制在没启用Rabbit情况下. 不将 @RabbitListener 修饰的监听器注册为Bean, 不然会导致无限尝试重连** @author xxm* @since 2022/12/12*/
public class OnRabbitEnable implements Condition {private final String rabbitPropertiesPrefix = "com.jeeplus.common.rabbit";/*** @param context* @param metadata* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {RabbitMqProperties rabbitMqProperties = Binder.get(context.getEnvironment()).bind(rabbitPropertiesPrefix, RabbitMqProperties.class).orElse(new RabbitMqProperties());return rabbitMqProperties.isEnable();}}

4.BootxRabbitListenerConfigurer

package com.jeeplus.common.rabbit.configuration;import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;/*** Rabbit 侦听器配置器** @author xxm* @since 2021/6/25*/
@Configuration
@RequiredArgsConstructor
public class BootxRabbitListenerConfigurer implements RabbitListenerConfigurer {private final DefaultMessageHandlerMethodFactory jsonHandlerMethodFactory;@Overridepublic void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {registrar.setMessageHandlerMethodFactory(jsonHandlerMethodFactory);}}

5.BootxRabbitListenerConfigurer

package com.jeeplus.common.rabbit.configuration;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;/*** 消息队列配置** @author xxm* @since 2021/6/25*/
@EnableRabbit
@Configuration
public class RabbitMqConfigurer {/*** 注册 RabbitTemplate 对象, 使用默认序列化方式*/@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, ObjectMapper objectMapper) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);// 使用系统同版jackson 序列化配置rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter(objectMapper));return rabbitTemplate;}/*** 添加默认消息序列化方式, 使用默认序列化方式*/@Beanpublic DefaultMessageHandlerMethodFactory jsonHandlerMethodFactory(ObjectMapper objectMapper) {DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();// 这里的转换器设置实现了 通过 @Payload 注解 自动反序列化message bodyMappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();converter.setObjectMapper(objectMapper);factory.setMessageConverter(converter);return factory;}}

6.RabbitMqConfigurer

package com.jeeplus.common.rabbit.configuration;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;/*** 消息队列配置** @author xxm* @since 2021/6/25*/
@EnableRabbit
@Configuration
public class RabbitMqConfigurer {/*** 注册 RabbitTemplate 对象, 使用默认序列化方式*/@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, ObjectMapper objectMapper) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);// 使用系统同版jackson 序列化配置rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter(objectMapper));return rabbitTemplate;}/*** 添加默认消息序列化方式, 使用默认序列化方式*/@Beanpublic DefaultMessageHandlerMethodFactory jsonHandlerMethodFactory(ObjectMapper objectMapper) {DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();// 这里的转换器设置实现了 通过 @Payload 注解 自动反序列化message bodyMappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();converter.setObjectMapper(objectMapper);factory.setMessageConverter(converter);return factory;}}

7.RabbitMqProperties

package com.jeeplus.common.rabbit.configuration;import com.jeeplus.common.rabbit.conditional.ConditionalOnRabbit;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** MQTT配置** @author xxm* @since 2022/12/12*/
@Getter
@Setter
@ConfigurationProperties("com.jeeplus.common.rabbit")
public class RabbitMqProperties {/*** 是否开启 RabbitMQ功能,* @see ConditionalOnRabbit 配合此注解使用*/private boolean enable = false;}

8.RabbitMqCommonAutoConfiguration

package com.jeeplus.common.rabbit;import org.springframework.boot.autoconfigure.SpringBootApplication;/*** RabbitMQ配置** @author xxm* @since 2022/5/3*/
@SpringBootApplication
public class RabbitMqCommonAutoConfiguration {}

在这里插入图片描述

9.org.springframework.boot.autoconfigure.AutoConfiguration.imports

RabbitMqCommonAutoConfiguration

10.spring.factories

## 配置自定义 starter 的自动化配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.jeeplus.common.rabbit.RabbitMqCommonAutoConfiguration

3. nacos配置

哪一个服务模块需要消息队列,就在对应的yml文件中配置 rabbit链接
在这里插入图片描述

  #rabbitmqrabbitmq:host: localhostport: 5627username: rootpassword: root123virtual-host: /publisher-confirm-type: correlatedlistener:simple:acknowledge-mode: manual

4.服务中调用rabbitmq

建立两个包,配置类和监听类

在这里插入图片描述

1.mq模板配置

package com.jeeplus.duxin.config;import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** mq模板* @author lgn* @date 2023/10/28 10:15*/
@Configuration
public class MyRabbitConfig {private RabbitTemplate rabbitTemplate;@Primary@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);this.rabbitTemplate = rabbitTemplate;rabbitTemplate.setMessageConverter(messageConverter());initRabbitTemplate();return rabbitTemplate;}@Beanpublic MessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}/*** 定制RabbitTemplate* 1、服务收到消息就会回调*      1、spring.rabbitmq.publisher-confirms: true*      2、设置确认回调* 2、消息正确抵达队列就会进行回调*      1、spring.rabbitmq.publisher-returns: true*         spring.rabbitmq.template.mandatory: true*      2、设置确认回调ReturnCallback** 3、消费端确认(保证每个消息都被正确消费,此时才可以broker删除这个消息)**/// @PostConstruct  //MyRabbitConfig对象创建完成以后,执行这个方法public void initRabbitTemplate() {/*** 1、只要消息抵达Broker就ack=true* correlationData:当前消息的唯一关联数据(这个是消息的唯一id)* ack:消息是否成功收到* cause:失败的原因*///设置确认回调rabbitTemplate.setConfirmCallback((correlationData,ack,cause) -> {System.out.println("confirm...correlationData["+correlationData+"]==>ack:["+ack+"]==>cause:["+cause+"]");});/*** 只要消息没有投递给指定的队列,就触发这个失败回调* message:投递失败的消息详细信息* replyCode:回复的状态码* replyText:回复的文本内容* exchange:当时这个消息发给哪个交换机* routingKey:当时这个消息用哪个路邮键*/rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey) -> {System.out.println("Fail Message["+message+"]==>replyCode["+replyCode+"]" +"==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");});}
}

2.服务交换机 队列设置

初始化交换机,队列,建立绑定。

package com.jeeplus.duxin.config;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;/*** 服务交换机 队列设置* @author lgn* @date 2023/10/28 10:16*/
@Configuration
public class MyRabbitMQConfig {/* 容器中的Queue、Exchange、Binding 会自动创建(在RabbitMQ)不存在的情况下 *//*    *//*** 初始化队列* 死信队列** @return*//*@Beanpublic Queue orderDelayQueue() {*//*Queue(String name,  队列名字boolean durable,  是否持久化boolean exclusive,  是否排他boolean autoDelete, 是否自动删除Map<String, Object> arguments) 属性*//*HashMap<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange", "order-event-exchange");arguments.put("x-dead-letter-routing-key", "order.release.order");arguments.put("x-message-ttl", 60000); // 消息过期时间 1分钟Queue queue = new Queue("order.delay.queue", true, false, false, arguments);return queue;}*//*    *//*** 初始化队列* 普通队列** @return*//*@Beanpublic Queue orderReleaseQueue() {Queue queue = new Queue("order.release.order.queue", true, false, false);return queue;}*//*    *//**** TopicExchange* 创建topic类型的交换机* @return*//*@Beanpublic Exchange orderEventExchange() {*//**   String name,*   boolean durable,*   boolean autoDelete,*   Map<String, Object> arguments* *//*return new TopicExchange("order-event-exchange", true, false);}*//*    *//*** 路由和交换机进行绑定 设置路由key* @author lgn* @date 2023/10/28 10:33* @return Binding*//*@Beanpublic Binding orderCreateBinding() {*//** String destination, 目的地(队列名或者交换机名字)* DestinationType destinationType, 目的地类型(Queue、Exhcange)* String exchange,* String routingKey,* Map<String, Object> arguments* *//*return new Binding("order.delay.queue",Binding.DestinationType.QUEUE,"order-event-exchange","order.create.order",null);}*//*    @Beanpublic Binding orderReleaseBinding() {return new Binding("order.release.order.queue",Binding.DestinationType.QUEUE,"order-event-exchange","order.release.order",null);}*//*** 订单释放直接和库存释放进行绑定* @return*//*@Beanpublic Binding orderReleaseOtherBinding() {return new Binding("stock.release.stock.queue",Binding.DestinationType.QUEUE,"order-event-exchange","order.release.other.#",null);}*//*    *//*** 初始化队列* 商品秒杀队列* @return*//*@Beanpublic Queue orderSecKillOrrderQueue() {Queue queue = new Queue("order.seckill.order.queue", true, false, false);return queue;}@Beanpublic Binding orderSecKillOrrderQueueBinding() {//String destination, DestinationType destinationType, String exchange, String routingKey,// 			Map<String, Object> argumentsBinding binding = new Binding("order.seckill.order.queue",Binding.DestinationType.QUEUE,"order-event-exchange","order.seckill.order",null);return binding;}*//*** BOM模块的交换机* TopicExchange* 创建topic类型的交换机* @return*/@Beanpublic Exchange orderEventExchange() {/**   String name,*   boolean durable,*   boolean autoDelete,*   Map<String, Object> arguments* */return new TopicExchange("bom-event-exchange", true, false);}/*** 初始化BOM队列* @return*/@Beanpublic Queue bomMaintenanceQueue() {Queue queue = new Queue("bom.maintenance.queue", true, false, false);return queue;}/*** bom* 路由和交换机进行绑定 设置路由key* @author lgn* @date 2023/10/28 10:33* @return Binding*/@Beanpublic Binding bomCreateBinding() {/** String destination, 目的地(队列名或者交换机名字)* DestinationType destinationType, 目的地类型(Queue、Exhcange)* String exchange,* String routingKey,* Map<String, Object> arguments* */return new Binding("bom.maintenance.queue",Binding.DestinationType.QUEUE,"bom-event-exchange","bom.maintenance.create",null);}/*** 初始化产品存货档案队列* @return*/@Beanpublic Queue stockDocQueue() {Queue queue = new Queue("stock.doc.queue", true, false, false);return queue;}/*** 存货档案StockDoc* 路由和交换机进行绑定 设置路由key* @author lgn* @date 2023/10/28 10:33* @return Binding*/@Beanpublic Binding docCreateBinding() {/** String destination, 目的地(队列名或者交换机名字)* DestinationType destinationType, 目的地类型(Queue、Exhcange)* String exchange,* String routingKey,* Map<String, Object> arguments* */return new Binding("stock.doc.queue",Binding.DestinationType.QUEUE,"bom-event-exchange","stock.doc.create",null);}/*** 调用C++模块的交换机* TopicExchange* 创建topic类型的交换机* @return*/@Beanpublic Exchange cEventExchange() {/**   String name,*   boolean durable,*   boolean autoDelete,*   Map<String, Object> arguments* */return new TopicExchange("c-event-exchange", true, false);}/*** 初始化c++生成记录文件队列* @return*/@Beanpublic Queue cCreatFileQueue() {Queue queue = new Queue("c.creatfile.queue", true, false, false);return queue;}/*** 初始化c++签名队列* @return*/@Beanpublic Queue cDealQueue() {Queue queue = new Queue("c.deal.queue", true, false, false);return queue;}/** * 创建绑定关系* @author lgn* @date 2023/10/30 9:34* @return Binding*/@Beanpublic Binding cCreatFileCreateBinding() {/** String destination, 目的地(队列名或者交换机名字)* DestinationType destinationType, 目的地类型(Queue、Exhcange)* String exchange,* String routingKey,* Map<String, Object> arguments* */return new Binding("c.creatfile.queue",Binding.DestinationType.QUEUE,"c-event-exchange","c.creatFile.create",null);}/*** 创建绑定关系* @author lgn* @date 2023/10/30 9:34* @return Binding*/@Beanpublic Binding cDealBinding() {/** String destination, 目的地(队列名或者交换机名字)* DestinationType destinationType, 目的地类型(Queue、Exhcange)* String exchange,* String routingKey,* Map<String, Object> arguments* */return new Binding("c.deal.queue",Binding.DestinationType.QUEUE,"c-event-exchange","c.deal.create",null);}}

3.监听队列 接收消息

消费方消费消息

package com.jeeplus.duxin.listener;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;/*** 监听路由信息* @author lgn* @date 2023/10/28 10:33*/
@Slf4j
@Component
//@RabbitListener标注在方法上,直接监听指定的队列,此时接收的参数需要与发送时类型一致
//@RabbitListener 注解是指定某方法作为消息消费的方法,例如监听某 Queue 里面的消息。
@RabbitListener(queues = "bom.maintenance.queue")
public class MQTestListener {//@RabbitListener 可以标注在类上面,需配合 @RabbitHandler 注解一起使用//@RabbitListener 标注在类上面表示当有收到消息的时候,就交给 @RabbitHandler 的方法处理,根据接受的参数类型进入具体的方法中。@RabbitHandlerpublic void listener(String info,Channel channel, Message message) throws IOException {System.out.println("=============接收消息开始执行:"+info);try {channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);} catch (Exception e) {channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);}}
}

5.使用

使用起来也非常方便:
在业务service中直接调用,生产者消息发送。

	/*** mqTest* @author lgn* @date 2023/10/28 10:03* @return Object*/public String mqTest() {//TODO 订单创建成功,发送消息给MQrabbitTemplate.convertAndSend("bom-event-exchange","bom.maintenance.create","1234");return null;}

希望对你有用!

相关文章:

微服务框架SpringcloudAlibaba+Nacos集成RabbitMQ

目前公司使用jeepluscloud版本&#xff0c;这个版本没有集成消息队列&#xff0c;这里记录一下&#xff0c;集成的过程&#xff1b;这个框架跟ruoyi的那个微服务版本结构一模一样&#xff0c;所以也可以快速上手。 1.项目结构图&#xff1a; 配置类的东西做成一个公共的模块 …...

低代码开发,一场深度的IT效率革命

目录 一、前言 二、低代码迅速流行的理由 三、稳定性和生产率的最佳实践 四、程序员用低代码开发应用有哪些益处&#xff1f; 1、提升开发价值 2、利于团队升级 五、总结 一、前言 尽管IT技术支撑了全球的信息化浪潮&#xff0c;然而困扰行业已久的软件开发效率并未像摩尔定律那…...

虚拟串口软件使用介绍

对于上位机开发来说(特别是串口通信应用),上机位软件的调试尤为重要,但是上机位软件的调试并不关心硬件,只需要关注验证发送的数据帧的接收情况,为了便于调试,可以将上机位软件与串口软件互通,实现数据的交互,但由于互通需要串口,可以借助串口虚拟软件(VSPD),虚拟出…...

如何编写一份完整的软件测试报告?(进阶版)百分之90不知道

背景 作为测试从业者&#xff0c;编写测试用例&#xff0c;测试计划&#xff0c;测试报告都是必经之路&#xff0c;最近完成了年终述职以及版本准出&#xff0c;感觉测试报告或者各类报告真是职场人不可或缺的一项技能&#xff0c;趁着热乎劲&#x1f525;&#xff0c;写下一些…...

python企业微信小程序发送信息

python企业微信小程序发送信息 在使用下面代码之前先配置webhook 教程如下&#xff1a; https://www.bilibili.com/video/BV1oH4y1S7pN/?vd_sourcebee29ac3f59b719e046019f637738769 然后使用如下代码就可以发消息了&#xff1a; 代码如下&#xff1a; #codinggbk import r…...

Java入门篇 之 逻辑控制(练习题篇)

博主碎碎念: 练习题是需要大家自己打的请在自己尝试后再看答案哦&#xff1b; 个人认为&#xff0c;只要自己努力在将来的某一天一定会看到回报&#xff0c;在看这篇博客的你&#xff0c;不就是在努力吗&#xff0c;所以啊&#xff0c;不要放弃&#xff0c;路上必定坎坷&#x…...

Android Google登录并获取token(亲测有效)

背景&#xff1a; Android 需要用到Google的登录授权&#xff0c;用去token给到服务器&#xff0c;服务器再通过token去获取用户信息&#xff0c;实现第三方登录。 我们通过登录之后的email来获取token&#xff0c;不需要server_clientId&#xff1b;如果用server_clientId还…...

npm ERR! code ELIFECYCLE

问题&#xff1a; 一个老项目&#xff0c;现在想运行下&#xff0c;打不开了 npm install 也出错 尝试1 、使用cnpm npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install 还是不行 尝试2、 package.json 文件&#xff0c;去掉 那个插件 chorm…...

Mgeo:multi-modalgeographic language model pre-training

文章目录 question5.1 Geographic Encoder5.1.1 Encoding5.1.2 5.2 multi-modal pre-training 7 conclusionGeo-Encoder: A Chunk-Argument Bi-Encoder Framework for Chinese Geographic Re-Rankingabs ERNIE-GeoL: A Geography-and-Language Pre-trained Model and its Appli…...

[激光原理与应用-75]:西门子PLC系列选型

目录 一、西门子PLC PLC系列 二、西门子PLC S7 1200系列 2.1 概述 2.2 12xx系列比较 三、西门子 PLC 1212C系列 四、主要类别比较 4.1 AC/DC/RLY的含义 4.2 AC/DC/RLY与DC/DC/DC 4.3 直流输入与交流输入比较 4.4 继电器输出与DC输出的区别 一、西门子PLC PLC系列 …...

Linux上编译sqlite3库出现undefined reference to `sqlite3_column_table_name‘

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 在Ubuntu 18上编译sqlite3库后在运行程序时出现undefined reference to sqlite3_column_table_name’的错误。网上的说法是说缺少SQLITE_ENABLE_COLUMN_M…...

第十五章 EM期望极大算法及其推广

文章目录 导读符号说明混合模型伯努利混合模型(三硬币模型)问题描述三硬币模型的EM算法1.初值2.E步3.M步初值影响p,q 含义 EM算法另外视角Q 函数BMM的EM算法目标函数LEM算法导出 高斯混合模型GMM的EM算法1. 明确隐变量, 初值2. E步,确定Q函数3. M步4. 停止条件 如何应用GMM在聚…...

自动化测试如何准备测试数据

其实大部分类型的测试都需要去准备测试数据。 手工测试&#xff1a;一些基础数据&#xff0c;比如配置数据等等是需要去准备的&#xff1b;自动化测试&#xff1a;基础需要准备&#xff0c;现有数据&#xff0c;动态运行时产生的数据是需要准备的&#xff1b;性能测试&#xf…...

javaEE -13(6000字CSS入门级教程 - 2)

一&#xff1a;Chrome 调试工具 – 查看 CSS 属性 首先打开浏览器&#xff0c;接着有两种方式可以打开 Chrome 调试工具 直接按 F12 键鼠标右键页面 > 检查元素 点开检查即可 标签页含义&#xff1a; elements 查看标签结构console 查看控制台source 查看源码断点调试ne…...

vscode 使用python无法导入库

刚刚在使用vscode,编辑python时&#xff0c;在使用语句 import matplotlib.pyplot as plt 时出现报错&#xff0c;但是在命令行下和conda环境中没有报错 在尝试 pip uninstall matplotlib pip install matplotlib后无法解决 之后再发现是工作的目录出错导致的&#xff0c;…...

三维向量旋转

三维向量旋转 问题描述问题分析 v ⃗ ∣ ∣ \vec{v}_{||} v ∣∣​的旋转 v ⃗ ⊥ \vec{v}_{\bot} v ⊥​的旋转 v ⃗ \vec{v} v 的旋转结论致谢 问题描述 如图1所示&#xff0c;设一个向量 v ⃗ \vec{v} v 绕另一个向量 u ⃗ [ x , y , z ] T \vec{u}[x,y,z]^{T} u [x,y,z]T…...

顺序表——leetcode

原地删除数据 我们的思路这里给的是双指针&#xff0c;给两个指针&#xff0c;从前往后移动&#xff0c;如果不是val就覆盖&#xff0c;如果是我就跳过&#xff0c;大家一定要看到我们的条件是原地修改&#xff0c;所以我们不能另开一个数组来实现我们这道题目。 这里我们给两…...

Kaprekar 7641 - 1467= 6174

package homework;import java.util.Arrays;import util.StringUtil;/*** 数学黑洞数6174&#xff0c;即卡普雷卡尔&#xff08;Kaprekar&#xff09;常数&#xff0c; 它的算法如下&#xff1a; 取任意一个4位数&#xff08;4个数字均为同一个数的除外&#xff09;&#xff0…...

李宏毅机器学习笔记.Flow-based Generative Model(补)

文章目录 引子生成问题回顾&#xff1a;GeneratorMath BackgroundJacobian MatrixDeterminant 行列式Change of Variable Theorem简单实例一维实例二维实例 网络G的限制基于Flow的网络构架G的训练Coupling LayerCoupling Layer反函数计算Coupling Layer Jacobian矩阵计算Coupli…...

Java使用Spark入门级非常详细的总结

目录 Java使用Spark入门 环境准备 安装JDK 安装Spark 编写Spark应用程序 创建SparkContext 读取文本文件 计算单词出现次数 运行Spark应用程序 总结 Java使用Spark入门 本文将介绍如何使用Java编写Spark应用程序。Spark是一个快速的、通用的集群计算系统&#xff0c;它可以处理…...

实时口罩检测-通用部署教程:Windows WSL2环境下ModelScope模型本地加载

实时口罩检测-通用部署教程&#xff1a;Windows WSL2环境下ModelScope模型本地加载 1. 环境准备与WSL2配置 1.1 WSL2安装与设置 如果你使用的是Windows系统&#xff0c;首先需要安装WSL2&#xff08;Windows Subsystem for Linux 2&#xff09;。这是微软提供的Linux兼容层&…...

TCGA数据下载神器gdc-client实战:Win10系统闪退问题一网打尽

TCGA数据高效下载指南&#xff1a;gdc-client在Win10系统的深度优化与故障排除 1. 为什么选择gdc-client下载TCGA数据&#xff1f; 对于生物信息学研究者来说&#xff0c;获取TCGA&#xff08;癌症基因组图谱&#xff09;数据是开展肿瘤基因组学研究的第一步。然而&#xff0c;…...

中兴光猫高级管理:5分钟掌握zteOnu命令行工具实用指南

中兴光猫高级管理&#xff1a;5分钟掌握zteOnu命令行工具实用指南 【免费下载链接】zteOnu 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 中兴光猫作为家庭和企业网络的核心设备&#xff0c;其隐藏的高级功能往往被普通用户界面所限制。zteOnu是一个专门为中兴…...

通义千问3-VL-Reranker-8B新手教程:零基础学会混合检索排序

通义千问3-VL-Reranker-8B新手教程&#xff1a;零基础学会混合检索排序 1. 认识这个强大的多模态排序工具 想象一下&#xff0c;你正在管理一个包含文字、图片和视频的庞大数据库。当用户搜索"户外运动装备"时&#xff0c;系统返回了100个结果——有些是产品描述文…...

NEURAL MASK 模型调试技巧:使用IDE进行Python代码跟踪与问题定位

NEURAL MASK 模型调试技巧&#xff1a;使用IDE进行Python代码跟踪与问题定位 调试代码&#xff0c;尤其是涉及复杂模型加载和推理的代码&#xff0c;有时候就像在黑暗的房间里找一颗掉落的螺丝钉。你大概知道它就在那儿&#xff0c;但就是看不见摸不着。对于NEURAL MASK这类模…...

LeetCode 1089 复写零:用双指针从后往前填,保姆级图解避坑指南

LeetCode 1089 复写零&#xff1a;双指针逆向填充的视觉化拆解与实战避坑 当你第一次看到LeetCode 1089题时&#xff0c;可能会觉得"复写零"这个操作听起来简单——不就是遇到0就多写一个吗&#xff1f;但真正动手实现时&#xff0c;很多人会在指针移动、边界处理和数…...

ROS机器人开发实战:利用tf2库高效处理四元数、欧拉角与旋转矩阵的转换

1. 为什么机器人开发需要处理多种姿态表示 在机器人开发中&#xff0c;我们经常需要处理各种姿态数据。无论是移动机器人的定位信息、机械臂末端执行器的位姿&#xff0c;还是传感器数据的融合&#xff0c;都离不开对物体在三维空间中位置和朝向的描述。但有趣的是&#xff0c;…...

Pixel Mind Decoder 数据结构优化:提升批量文本情绪处理效率

Pixel Mind Decoder 数据结构优化&#xff1a;提升批量文本情绪处理效率 1. 为什么需要优化批量处理 当你需要分析成千上万条用户评论或社交媒体内容时&#xff0c;逐条调用情绪分析模型会变得非常低效。就像在快餐店点餐一样&#xff0c;一个一个处理订单远不如批量处理来得…...

Java线程池中如何用TransmittableThreadLocal避免变量丢失?附完整Demo

Java线程池中TransmittableThreadLocal的实战应用与避坑指南 在Java高并发编程中&#xff0c;线程池是提升性能的利器&#xff0c;但线程复用机制却给上下文传递带来了挑战。当我们在父线程设置变量&#xff0c;子线程却无法获取时&#xff0c;这种"断链"现象常让开发…...

不止于部署:用Docker和Helm在K8s上玩转JFrog Artifactory + Xray安全扫描全家桶

云原生时代的DevSecOps实践&#xff1a;基于Docker与Helm的JFrog全家桶深度集成指南 当微服务架构成为企业数字化转型的标配&#xff0c;如何高效管理海量制品并确保其安全性&#xff0c;已成为每个技术团队必须面对的挑战。传统单机部署模式在弹性扩展、灾备能力等方面的局限性…...