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

SpringBoot整合Rabbitmq(包括docker配置Rabbitmq的详细过程)

一、什么是mq

MQ(message queue),从字面意思上看就个 FIFO 先入先出的队列,只不过队列中存放的内容是 message 而已,它是一种具有接收数据、存储数据、发送数据等功能的技术服务。

在互联网架构中,MQ 是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务,用于上下游传递消息。使用了 MQ 之后,消息发送上游只需要依赖 MQ,不用依赖其他服务

常见的MQ消息中间件有很多,例如ActiveMQRabbitMQKafkaRocketMQ等等。

二、什么是Rabbitmq

2007 年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。

  • 优点:由于 erlang 语言的高并发特性,性能较好;吞吐量到万级,MQ 功能比较完备、健壮、稳定、易用、跨平台、支持多种语言如Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持 AJAX 文档齐全;开源提供的管理界面非常棒,用起来很好用,社区活跃度高;更新频率相当高。

  • 缺点:商业版需要收费,学习成本较高。

  • 选用场景:结合 erlang 语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,管理界面用起来十分方便,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的 RabbitMQ。

三、在linux系统上用docker部署Rabbitmq详细步骤

  1. 前提条件

    确保你的系统已经安装了 Docker。如果尚未安装,可以参考 如何部署Docker 使用 Docker 部署 RabbitMQ 的详细指南_docker部署rabbitmq-CSDN博客

  2. 拉取 RabbitMQ 镜像

    从 Docker Hub 拉取 RabbitMQ 的镜像,推荐使用带有管理界面的版本:

    docker pull rabbitmq:management

  3. 创建挂载目录

    创建一个目录用于持久化 RabbitMQ 的数据,避免容器重启后数据丢失:

    mkdir -p /usr/local/docker/rabbitmq

  4. 启动 RabbitMQ 容器

    运行以下命令启动 RabbitMQ 容器:

    docker run -d --name rabbitmq \-v /usr/local/docker/rabbitmq:/var/lib/rabbitmq \-p 5672:5672 -p 15672:15672 \-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin \rabbitmq:management   
    • -d:后台运行容器。

    • --name rabbitmq:为容器指定名称。

    • -v:将宿主机的目录挂载到容器内,用于数据持久化。

    • -p:映射容器端口到宿主机端口,5672 用于消息通信,15672 用于管理界面。

    • -e:设置默认的用户名和密码

  5. 访问管理界面

    打开浏览器,访问 http://localhost:15672,使用默认用户名和密码(guest/guest)登录,出现以下界面则启动成功

    **提示:RabbitMQ是采用 Erlang语言开发的,所以系统环境必须提供 Erlang环境,需要是安装 Erlang,但是如果是通过docker拉取的RabbitMQ,RabbitMQ 的官方 Docker 镜像已经预装了 Erlang。当你从 Docker Hub 拉取并运行 RabbitMQ 镜像时,Erlang 环境已经内置在镜像中,无需额外安装。**

此时,你的RabbitMQ便配置成功了

四、RabbitMQ管控台使用

参考文章:RabbitMQ的管控台的使用说明-腾讯云开发者社区-腾讯云

五、RabbitMQ四大核心概念

  • 生产者:产生数据发送消息的程序是生产者。

  • 交换机:交换机是 RabbitMQ 非常重要的一个部件,一方面它接收来自生产者的消息,另一方面它将消息推送到队列中。交换机必须确切知道如何处理它接收到的消息,是将这些消息推送到特定队列还是推送到多个队列,亦或者是把消息丢弃,这个是由交换机类型决定的。

  • 队列:队列是 RabbitMQ 内部使用的一种数据结构,尽管消息流经 RabbitMQ 和应用程序,但它们只能存储在队列中。队列仅受主机的内存和磁盘限制的约束,本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据。

  • 消费者:消费与接收具有相似的含义。消费者大多时候是一个等待接收消息的程序。请注意生产者,消费者和消息中间件很多时候并不在同一机器上。同一个应用程序既可以是生产者又是可以是消费者。

六、springboot简单整合RabbitMQ

  1. 在pom.xml文件中导入RabbitMQ依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

  2. 在application.yml配置RabbitMQ

    spring:rabbitmq:#rabbitmq的iphost: 你的rabbit配置的linuxipusername: guestpassword: guest#虚拟主机stream:virtual-host: /port: 5672listener:simple:#消费者的最小数量concurrency: 10#消费者的最大数量max-concurrency: 10#限制消费者,每次只能处理一条消息,处理完才能继续下一条消息prefetch: 1#启动时,是否默认启动容器,默认trueauto-startup: true#被拒绝后,重新进入队列default-requeue-rejected: truetemplate:retry:#启用重试机制,默认为falseenabled: true#设置初始化的重试时间间隔initial-interval: 1000ms#重试最大次数,默认是3max-attempts: 3#重试最大时间间隔,默认是10smax-interval: 10000ms#重试时间间隔的乘数multiplier: 1

  3. 创建RibbitMQ的配置类 RabbitMQConfig.java

    @Configuration
    public class RabbitMQConfig {private static final String QUEUE = "queue";//创建队列//true:表示持久化//队列在默认情况下放到内存,rabbitmq重启后就丢失了,如果希望重启后,队列//数据还能使用,就需要持久化@Beanpublic Queue queue1(){return new Queue(QUEUE,true);}
    }
        
  4. 创建消息的生产者和消费者

  • 创建生产者MQSender

    @Slf4j
    @Service
    public class MQSender {
    ​//装配RabbitTemplate ->操作RabbitMQ@Resourceprivate RabbitTemplate rabbitTemplate;
    ​//方法:发送消息public void send(Object msg){log.info("发送消息-->" + msg);//指定你队列的名字rabbitTemplate.convertAndSend("queue",msg);}
    }

  • 创建消费者MQReceiver

    @Service
    @Slf4j
    public class MQReceiver {//方法:接收消息@RabbitListener(queues = "queue")public void receive(Object msg){log.info("接收到的消息-->" + msg);}}  

5、创建controller层调用消息生产者

@RequestMapping("/rabbit")
@RestController
public class RabbitMQConteroller {
​@Resourceprivate MQSender mqSender;
​
​@GetMapping("/mq")//方法:调用消息生产者,发送消息public void mq(){mqSender.send("hello,消费者~");}
}

此时,看到控制台输出

表示你已经成功整合了RabbitMQ

七、RabbitMQ交换机介绍

  • RabbitMQ 消息传递模型的核心思想是:生产者生产的消息从不会直接发送到队列。实际上,通常生产者甚至都不知道这些消息传递传递到了哪些队列中。

  • 相反,生产者只能将消息发送到交换机(exchange),交换机工作的内容非常简单,一方面它接收来自生产者的消息,另一方面将它们推入队列。交换机必须确切知道如何处理收到的消息。是应该把这些消息放到特定队列还是说把他们到许多队列中还是说应该丢弃它们。这就的由交换机的类型来决定。

  • 交换机的类型有四种:直接(direct)、主题(topic)、标题(headers)、扇出(fanout),每一个都有,以下我们对四种交换机根据简单例子介绍

八、RabbitMQ交换机的在springboot中使用的简单例子

fanout模式

  1. fanout就是广播模式,就是把交换机(Exchange)里的消息队列发送给所有绑定该交换机的队列,忽略routingKey(也就是路由)

  2. 示意图

  • 生产者把消费发送给指定的交换机

  • 再把交换机的消息发送给所有绑定该交换机的队列,忽略路由

代码示例:

  1. 创建--fanout--广播模式队列和交换机示例,在RibbitMQConfig中配置示例

//--fanout--广播模式队列示例
private static final String QUEUE1 = "queue1_fanout01";
private static final String QUEUE2 = "queue2_fanout02";
private static final String EXCHANGE = "fanoutExchange";
​//创建队列//true:表示持久化//队列在默认情况下放到内存,rabbitmq重启后就丢失了,如果希望重启后,队列//数据还能使用,就需要持久化@Beanpublic Queue queue1(){return new Queue(QUEUE1,true);}
​@Beanpublic Queue queue2(){return new Queue(QUEUE2,true);}//创建Fanout交换机@Beanpublic FanoutExchange exchange(){return new FanoutExchange(EXCHANGE);}
​//将queue1_fanout01,2队列绑定到交换机EXCHANGE,此时如果消息发送者发送消息到交换机,因为//是广播模式,与其交换机绑定的所有队列都可以接收到消息@Beanpublic Binding binding01(){return BindingBuilder.bind(queue1()).to(exchange());}
​@Beanpublic Binding binding02(){return BindingBuilder.bind(queue2()).to(exchange());}

2.在MQSender消息生产者配置方法(消息生产者和消费者都是服务提供者,所以记得加@Service注解)

//方法:发送消息到交换机
//这里的空串是因为fanout要屏蔽路由
public void sendFanout(Object msg){log.info("发送消息->" + msg);rabbitTemplate.convertAndSend("fanoutExchange","",msg);
}
3.在MQReceiver消息消费者接收消息@RabbitListener(queues = "queue1_fanout01") //表示监听的队列是哪个
public void receive1(Object msg){log.info("queue1_fanout01接收到的消息-->" + msg);
}
​
@RabbitListener(queues = "queue2_fanout02")
public void receive2(Object msg){log.info("queue2_fanout02接收到的消息-->" + msg);
}
4.在controller中调用消息生产者方法//调用生产者,发送消息到交换机
@GetMapping("/mq/fanout")
public void fanout(){mqSender.sendFanout("hello,交换机");
}

5.观看控制台输出如下表示成功

direct模式

  1. direct就是路由模式,路由模式是在使用交换机的同时,生产者指定路由发送数据,消费者绑定路由接收数据。

  2. 与广播模式不同的是,广播模式只要是绑定了交换机的队列都会收到生产者向交换机推送过来的数据,而路由模式下加了一个路由设置,生产者向交换机发送数据时,会声明发送到交换机下的哪个路由,并且只有当消费者的队列绑定了交换机并且声明了路由,才会收到数据

  3. 示意图

代码示例

  1. 创建direct路由模式示例

    //--direct--路由模式示例
    private static final String QUEUE3 = "queue_direct01";
    private static final String QUEUE4 = "queue_direct02";
    private static final String EXCHANGE2 = "directExchange";
    ​
    //路由模式,定义路由private static final String ROUTING_KEY01 = "queue.red";private static final String ROUTING_KEY02 = "queue.green";
    ​//direct-----@Beanpublic Queue queue3(){return new Queue(QUEUE3,true);}
    ​@Beanpublic Queue queue4(){return new Queue(QUEUE4,true);}
    ​//配置direct交换机@Beanpublic DirectExchange exchange_direct(){return new DirectExchange(EXCHANGE2);}
    ​//direct绑定交换机//.with:指定路由@Beanpublic Binding binding_direct1(){return BindingBuilder.bind(queue3()).to(exchange_direct()).with(ROUTING_KEY01);
    ​}
    ​@Beanpublic Binding binding_direct2(){return BindingBuilder.bind(queue4()).to(exchange_direct()).with(ROUTING_KEY02);
    ​}

  2. 在消息生产者配置发送消息方法

    //方法:发送消息到direct交换机,并且指定路由
    //这时我们如果调用sendDirect1方法,会将消息发送到交换机的queue.red路由,在配置文件中queue3绑定了
    //路由queue.red,所有只有与queue3队列绑定的消费者才能接收到消息
    public void sendDirect1(Object msg){log.info("发送消息->" + msg);rabbitTemplate.convertAndSend("directExchange","queue.red",msg);
    }
    ​
    public void sendDirect2(Object msg){log.info("发送消息->" + msg);rabbitTemplate.convertAndSend("directExchange","queue.green",msg);
    }

  3. 配置消息接收者

    @RabbitListener(queues = "queue_direct01")
    public void queue_direct01(Object msg){log.info("queue_direct01接收到的消息-->" + msg);
    }
    ​
    @RabbitListener(queues = "queue_direct02")
    public void queue_direct02(Object msg){log.info("queue_direct02接收到的消息-->" + msg);
    }

  4. 配置controller

//调用生产者,发送消息到交换机
@GetMapping("/mq/direct1")
public void direct1(){mqSender.sendDirect1("hello,jack");
}
​
@GetMapping("/mq/direct2")
public void direct2(){mqSender.sendDirect2("hello,tom");
}

5.此时,调用direct1控制台输出

调用direct2输出

topic模式

  1. direct模式会造成路由RoutingKey堆积太多,而实际开发往往是按照某个规则来进行路由匹配的,RabbitMQ提供了Topic模式来适应这种需求

  2. Topic模式是direct模式上的一种扩展叠加,扩展叠加了模糊路由RoutingKey的模式,可以理解为是模糊的路由匹配模式

    • *(星号):可以(只能匹配到一个单词)

    • #(井号):可以匹配多个单词

    • 这里是指一个完整的英语单词,而不是一个字母

  3. 示意图:

代码示例:

  1. 配置topic路由模式示例

    package com.yw.config;
    ​
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.TopicExchange;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    ​
    @Configuration
    public class RabbitMQTopicConfig {
    ​private static final String QUEUE1 = "queue_topic01";private static final String QUEUE2 = "queue_topic02";private static final String EXCHANGE = "topicExchange";private static final String KEY01 = "#.queue.#";private static final String KEY02 = "*.queue.#";
    ​
    ​@Beanpublic Queue topic_queue1(){return new Queue(QUEUE1);}
    ​@Beanpublic Queue topic_queue2(){return new Queue(QUEUE2);}
    ​@Beanpublic TopicExchange topicExchange(){return new TopicExchange(EXCHANGE);}
    ​@Beanpublic Binding binding_topic1(){return BindingBuilder.bind(topic_queue1()).to(topicExchange()).with(KEY01);
    ​}
    ​@Beanpublic Binding binding_topic2(){return BindingBuilder.bind(topic_queue2()).to(topicExchange()).with(KEY02);
    ​}
    ​
    }

  2. 配置消息生产者方

     //方法:发送消息到topic交换机,并且指定路由//此时调用sendTopic1根据路由KEY02前面为星号,所以此路由的队列不能接收到消息public void sendTopic1(Object msg){log.info("发送消息->" + msg);rabbitTemplate.convertAndSend("topicExchange","hello.hello.queue.green",msg);}
    ​
    //两个队列都满足路由,都可以接收消息public void sendTopic2(Object msg){log.info("发送消息->" + msg);rabbitTemplate.convertAndSend("topicExchange","hello.queue.green",msg);}
  3. 配置消息消费者方法

    @RabbitListener(queues = "queue_topic01")
    public void queue_topic01(Object msg){log.info("queue_topic01接收到的消息-->" + msg);
    }
    ​
    @RabbitListener(queues = "queue_topic02")
    public void queue_topic02(Object msg){log.info("queue_topic02接收到的消息-->" + msg);
    }

  4. 配置controller

    @GetMapping("/mq/topic1")
    public void topic1(){mqSender.sendTopic1("hello,tom");
    }
    ​
    @GetMapping("/mq/topic2")
    public void topic2(){mqSender.sendTopic2("hello,tom");
    }

  5. 调用topic1控制台输出

  6. 调用topic2控制台输出

headers模式

  1. headers交换机是一种比较复杂且少见的交换机,不同于direct和topic,它不关心路由key是否匹配,而只关心header中的key-value是否匹配,有点类似与http里面的请求头

  2. headers头路由模型中,消息是根据prop,即请求头中的k-v来匹配的

  3. 绑定的队列指定的headers中必须包含一个“x-match"的键

  4. “x-match"的键有两个:all和any

    • all:表示绑定对队列/消费方 指定的所有的k-v都必须在消息header中出现并匹配

    • any:表示绑定对队列/消费方 指定的的k-v至少有一个在消息header中出现并匹配

代码示例

  1. headers模式的示例

    package com.yw.config;
    ​
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.HeadersExchange;
    import org.springframework.amqp.core.Queue;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    ​
    ​
    import java.util.HashMap;
    import java.util.Map;
    ​
    @Configuration
    public class RabbitMQHeadersConfig {private static final String QUEUE1 = "queue_headers01";private static final String QUEUE2 = "queue_headers02";private static final String EXCHANGE = "headersExchange";
    ​//创建队列@Beanpublic Queue headers_queue1() {return new Queue(QUEUE1);}
    ​@Beanpublic Queue headers_queue2() {return new Queue(QUEUE2);}
    ​
    ​//创建交换机@Beanpublic HeadersExchange headersExchange(){return new HeadersExchange(EXCHANGE);}
    ​
    ​//创建连接@Beanpublic Binding headersBinding01(){//先定义k-v因为可以有多个,所以将其放入mapMap<String,Object> hMap = new HashMap<>();hMap.put("color","red");hMap.put("speed","low");//whereAny(hMap):whereAny是指只要你带入的k-v是hMap的任意一个匹配就可以return BindingBuilder.bind(headers_queue1()).to(headersExchange()).whereAny(hMap).match();
    ​}
    ​@Beanpublic Binding headersBinding02(){//先定义k-v因为可以有多个,所以将其放入mapMap<String,Object> hMap = new HashMap<>();hMap.put("color","red");hMap.put("speed","fast");//whereAny(hMap):whereAny是指只要你带入的k-v是hMap的任意一个匹配就可以return BindingBuilder.bind(headers_queue2()).to(headersExchange()).whereAll(hMap).match();
    ​}
    ​
    }

  2. 创建消息生产者方法

    //方法:发送消息到headers交换机,并且指定需要匹配的k-v
    //调用sendHeader01,因为其setHeader了两个属性值,与配置的两个队列都匹配,所以两个队列都可以收到消息
    
    public void sendHeader01(String msg){log.info("发送消息->" + msg);//创建消息属性MessagePropertiesMessageProperties properties = new MessageProperties();properties.setHeader("color","red");properties.setHeader("speed","fast");//创建message对象【包含了发送的消息本身和属性】Message message = new Message(msg.getBytes(), properties);rabbitTemplate.convertAndSend("headersExchange","",message);
    }
    ​
    public void sendHeader02(String msg){log.info("发送消息->" + msg);//创建消息属性MessagePropertiesMessageProperties properties = new MessageProperties();properties.setHeader("color","red");properties.setHeader("speed","normal");//创建message对象【包含了发送的消息本身和属性】Message message = new Message(msg.getBytes(), properties);rabbitTemplate.convertAndSend("headersExchange","",message);
    }

  3. 创建消息消费者接收消息

    @RabbitListener(queues = "queue_headers01")
    public void queue_headers01(Message msg){log.info("queue_topic01接收到的消息对象-->" + msg);log.info("queue_topic01接收到的消息-->" + new String(msg.getBody()));
    }
    ​
    @RabbitListener(queues = "queue_headers02")
    public void queue_headers02(Message msg){log.info("queue_topic02接收到的消息对象-->" + msg);log.info("queue_topic02接收到的消息-->" + new String(msg.getBody()));
    }

  4. 配置controller

    @GetMapping("/mq/headers1")
    public void headers1(){mqSender.sendHeader01("hello,red");
    }
    ​
    @GetMapping("/mq/headers2")
    public void headers2(){mqSender.sendHeader02("hello,great");
    }

  5. 调用headers1方法控制台输出

  6. 调用headers2方法控制台输出

至此,文章结束。

相关文章:

SpringBoot整合Rabbitmq(包括docker配置Rabbitmq的详细过程)

一、什么是mq MQ(message queue)&#xff0c;从字面意思上看就个 FIFO 先入先出的队列&#xff0c;只不过队列中存放的内容是 message 而已&#xff0c;它是一种具有接收数据、存储数据、发送数据等功能的技术服务。 在互联网架构中&#xff0c;MQ 是一种非常常见的上下游“逻…...

20个常用的初级Java笔试题及其参考答案

### 1. Java基本数据类型有哪些? - **答案**:Java中的基本数据类型有: - `byte`:8位 - `short`:16位 - `int`:32位 - `long`:64位 - `float`:32位 - `double`:64位 - `char`:16位(Unicode字符) - `boolean`:表示真或假(没有固定大小) ### 2. Java中的字符串是可…...

矫平机:工业制造的精密“雕刻师”

在金属加工的浩瀚图景中&#xff0c;矫平机犹如一位沉默的雕塑大师&#xff0c;用机械的精准与科学的智慧&#xff0c;将扭曲变形的板材重塑为工业艺术的杰作。从新能源电池极片到空间站耐压舱体&#xff0c;矫平工艺贯穿现代制造的每一处精度巅峰。 一、核心技术&#xff1a;从…...

游戏数据分析,力扣(游戏玩法分析 I~V)mysql+pandas

力扣的游戏玩法分析 I~V&#xff0c; ps&#xff1a;虽然表结构不变但是力扣输入示例数据有些许变化&#xff0c;所以你使用上一题的数据跑下一题的代码可能产生的结果和示例中的不一样&#xff0c;建议点击连接到力扣中直接运行&#xff01; 目录 1. 游戏玩法分析 I mysql …...

C++之哈希

目录 一、unordered_set 1.1、unordered_set的介绍 1.2、unordered_set和set的使用差异 二、unordered_map 2.1、unordered_map和map的差异 2.2、unordered_multimap/unordered_multiset 三、哈希表 3.1、哈希概念 3.1.1、直接定地址法 3.1.2、哈希冲突 3.1.3、负载…...

DSP、MCU、FPGA 的详细总结

一、核心定义与特点 类型定义核心特点DSP&#xff08;数字信号处理器&#xff09;专为高速数字信号处理设计的处理器- 哈佛架构&#xff0c;单周期乘加&#xff08;MAC&#xff09; - 实时性强&#xff0c;低延迟处理流式数据 - 专用指令集优化算法&#xff08;如FFT、滤波&am…...

linux学习 3.用户的操作

用户 建议在系统操作的时候不要一直使用root用户&#xff0c;因为root用户具有最高权限&#xff0c;你可能因为某些操作影响了你的系统&#xff0c;采用子用户则可以避免这一点 这里的学习不用太深入&#xff0c;掌握如何创建删除切换即可(除非你要做详细的用户管理&#xff0…...

闭坑-- `a-auto-complete` 组件中的 `options` 数据存在重复

当 ant-design 的 a-auto-complete 组件中的 options 数据存在重复时&#xff0c;可能会导致以下问题&#xff1a; 1. 交互问题 键盘导航失效&#xff1a; 使用键盘上下键选择时&#xff0c;可能会在重复项之间跳转&#xff0c;无法正常移动到下一个选项。选择结果不准确&…...

【Rust基础】使用Rocket构建基于SSE的流式回复

背景 我们正在使用Rust开发基于RAG的知识库系统&#xff0c;其中对于模型的回复使用了常用的SSE&#xff0c;Web框架使用Rocket&#xff0c;Rocket提供了一个简单的方式支持SSE&#xff0c;但没有会话保持、会话恢复等功能&#xff0c;因此我们自己简单实现这两个功能。 使用R…...

一种改进的CFAR算法用于目标检测(解决多目标掩蔽)

摘要 恒虚警率&#xff08;CFAR&#xff09;技术在雷达自动检测过程中起着关键作用。单元平均&#xff08;CA&#xff09;CFAR算法在几乎所有的多目标情况下都会受到掩蔽效应的影响。最小单元平均&#xff08;SOCA&#xff09;CFAR算法仅当干扰目标位于参考窗口的前后方时才具有…...

什么是人工智能芯片?

行业专家指出&#xff0c;许多智能设备和物联网设备都是由某种形式的人工智能(AI)驱动的——无论是语音助理、面部识别摄像头&#xff0c;还是电脑。这些设备需要采用某种技术为它们进行的数据处理提供支持。有些设备需要在云平台的大型数据中心处理数据&#xff0c;而也有一些…...

0.深入探秘 Rust Web 框架 Axum

在当今的 Web 开发领域&#xff0c;Rust 凭借其出色的性能、内存安全性和并发处理能力&#xff0c;正逐渐崭露头角。而 Axum 作为 Rust 生态系统中一款备受瞩目的 Web 框架&#xff0c;更是为开发者提供了高效、灵活且强大的工具&#xff0c;用于构建现代化的 Web 应用程序。本…...

深度监听 ref 和 reactive 的区别详解

深度监听 ref 和 reactive 的区别详解 一、ref 的深度监听&#xff08;示例代码&#xff09;关键点&#xff1a;1. ref 的存储方式&#xff1a;2. 监听 ref 的特性 二、reactive 的深度监听&#xff08;示例代码&#xff09;关键点&#xff1a;1. reactive 的深度响应性2. 监听…...

面向对象—有理数类的设计

目录 1.代码呈现 1.1编写toString、equals方法 1.2测试代码 1.3有理数类的代码 2.论述题 3.有理类设计 1.代码呈现 1.1编写toString、equals方法 (1)toString方法 Overridepublic String toString(){if(this.v20){return "Undefined";}return this.v1 "/…...

OpenHarmony Camera开发指导(四):相机会话管理(ArkTS)

概述 相机在使用预览、拍照、录像、获取元数据等功能前&#xff0c;都需要先创建相机会话。 相机会话Session的功能如下&#xff1a; 配置相机的输入流和输出流。 配置输入流即添加设备输入&#xff0c;通俗来讲即选择某一个摄像头进行拍照录像&#xff1b;配置输出流&#x…...

Linux电源管理(三),CPUIdle 和 ARM的PSCI

更多linux系统电源管理相关的内容请看&#xff1a;Linux电源管理、功耗管理 和 发热管理 (CPUFreq、CPUIdle、RPM、thermal、睡眠 和 唤醒)-CSDN博客 1 简介 Linux下的空闲进程cpuidle在内核中是一个子系统。cpuidle子系统所需要做的事情就是在CPU进入idle状态后&#xff0c;…...

【测试工具】JMeter使用小记

JMeter 使用小记 下载与安装 jdk 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk18-windowsJMeter 下载地址&#xff1a;https://jmeter.apache.org/download_jmeter.cgi 教程参考&#xff1a;JMeter下载及安装详细教程-CSDN博客 设置中文界…...

Obsidian的简单使用

一、安装并配置仓耳今楷字体 优化阅读体验&#xff0c;个人实测觉得正文用 仓耳今楷04-W03最合适&#xff08;前面的数字代表字体&#xff0c;数字越大&#xff0c;越偏向于楷体&#xff0c;而01就很像黑体。后面的数字代表粗细&#xff0c;正常粗细是W03&#xff0c;最粗是W0…...

docker的基础知识

Docker https://www.yuque.com/leifengyang/sutong 下载镜像 检索&#xff1a; docker search下载: docker pull列表: docker images删除 docker rmi启动容器 运行&#xff1a; docker run查看&#xff1a; docker ps停止&#xff1a; docker stop启动&#xff1a; …...

PcVue助力立讯:精密制造的智能化管控实践!

PcVue助力立讯&#xff1a; 精密制造的智能化管控实践&#xff01; 客户介绍 立讯精密&#xff08;Luxshare ICT&#xff0c;股票代码&#xff1a;002475&#xff09;成立于2004年5月24日&#xff0c;专注于为消费电子产品、汽车领域产品以及企业通讯产品提供从核心零部件、…...

深度学习-157-Dify工具之创建知识库

文章目录 1 硅基流动1.1 模型广场1.1.1 对话模型(免费)1.1.2 嵌入模型(免费)1.1.3 重排序模型(免费)1.2 模型调用1.2.1 文本对话1.2.2 文本嵌入2 构建知识库2.1 准备文档2.2 点击创建知识库2.3 设置嵌入参数2.4 召回测试3 创建聊天助手3.1 仅使用大模型3.2 结合知识库的大模型3…...

Oracle--安装Oracle Database23ai Free

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 官方文档&#xff1a; Get Started with Oracle Database 23ai | Oracle 一、安装的环境要求 本文同步使用Oracle Linux9的虚拟机进行操作 1、Orac…...

【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(三)

本篇博客给大家带来的是集合类在多线程下的使用和死锁的知识点还包括常见的面试题. &#x1f40e;文章专栏: JavaEE初阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&…...

【verilog】多个 if 控制同一个变量(后面会覆盖前面)非阻塞赋值真的并行吗?

非阻塞赋值 (<) 是“并行”的&#xff0c;但是代码顺序会影响结果&#xff1f;”这正是 Verilog 的硬件描述本质 vs 行为语义之间的微妙之处。 &#x1f4a1;1. 非阻塞赋值真的并行吗&#xff1f; 是的&#xff01;非阻塞赋值 < 从行为上是并行的&#xff0c;也就是说&a…...

C++事件驱动编程从入门到实战:深入理解与高效应用

C事件驱动编程从入门到实战&#xff1a;深入理解与高效应用 在现代软件开发中&#xff0c;事件驱动编程&#xff08;Event-Driven Programming&#xff09;作为一种流行的编程范式&#xff0c;被广泛应用于图形用户界面&#xff08;GUI&#xff09;、网络通信、游戏开发等众多…...

问题 | MATLAB比Python更有优势的特定领域

以下是关于MATLAB在特定领域相较于Python的优势的详细分析&#xff0c;结合其核心功能、行业应用及技术特性展开论述&#xff1a; 一、科学研究与工程计算 1. 数值计算的高效性 MATLAB的核心设计围绕矩阵运算展开&#xff0c;其底层对线性代数和数值计算进行了深度优化。例如…...

黑马商城项目(三)微服务

一、单体架构 测试高并发软件 二、微服务 三、SpringCloud 四、微服务拆分 黑马商城模块&#xff1a; 服务拆分原则&#xff1a; 拆分服务&#xff1a; 独立project&#xff1a; maven聚合&#xff1a; 拆分案例&#xff1a; 远程调用&#xff1a; package com.hmall.cart.…...

Qt界面卡住变慢的解决方法

本质原因: 当Qt界面出现卡顿或无响应时&#xff0c;通常是因为主线程&#xff08;GUI线程&#xff09;被耗时操作阻塞。 完全忘了。。。 Qt Creater解决方法 1. 定位耗时操作 目标&#xff1a;找到阻塞主线程的代码段。 方法&#xff1a; 使用QElapsedTimer测量代码执行时间…...

Flutter的原理及美团的实践(下)

Flutter的原理及性能实践 Flutter和原生性能对比 虽然使用原生实现&#xff08;左&#xff09;和Flutter实现&#xff08;右&#xff09;的全品类页面在实际使用过程中几乎分辨不出来&#xff1a; 但是我们还需要在性能方面有一个比较明确的数据对比。 我们最关心的两个页面…...

时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测

时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测 目录 时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab…...

【云安全】云原生- K8S IngressNightmare CVE-2025-1974(漏洞复现完整教程)

漏洞原理 CVE-2025-1974: The IngressNightmare in Kubernetes | Wiz Blog 分两方面&#xff1a; a、配置注入过程 构造一个恶意的Ingress资源&#xff0c;其中注入ssl_engine指令指向恶意共享库向准入控制器验证端点&#xff08;AdmissionWebhook&#xff09;发送Admissio…...

Tomcat与Servlet(2)

上篇文章&#xff1a; Tomcat与Servlethttps://blog.csdn.net/sniper_fandc/article/details/147278469?fromshareblogdetail&sharetypeblogdetail&sharerId147278469&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 上篇文章介绍了To…...

在高数据速度下确保信号完整性的 10 个关键策略

随着越来越多的传感器连接到系统&#xff0c;需要快速、可靠和安全地传输更多数据&#xff0c;对带宽和设计复杂性的需求也在增加。优先考虑的是确保从 A 发送到 B 的信号不会失真。 确保信号完整性 对于设计依赖于持续准确数据流的数据密集型应用程序的工程师来说&#xff0c…...

2025华中杯数学建模B题完整分析论文(共42页)(含模型、数据、可运行代码)

2025华中杯大学生数学建模B题完整分析论文 目录 一、问题重述 二、问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1解析 4.1.2问题1模型建立 4.1.3问题1样例代码&#xff08;仅供参考&#xff09; 4.1.4问题1求解结果&#xff08;仅供参考&am…...

UE5 自带的视频播放器

文章目录 文件夹准备添加一个文件媒体源方法1方法2 添加一个视频播放器播放视频直接播放使用网格体播放使用UI播放 播放视频的音乐媒体播放器常用的节点设置循环是用绝对路径播放视频&#xff0c;视频无需导入注册播放完成事件 文件夹准备 视频必须被放在Content/Moveis文件下…...

是德科技E5080B网络分析仪深度评测:5G/车载雷达测试实战指南

是德科技E5080B网络分析仪&#xff08;ENA系列&#xff09;是一款高性能射频测试仪器&#xff0c;广泛应用于通信、航空航天、半导体等领域&#xff0c;以下是其核心功能详解&#xff1a; 一、核心测试功能 多参数网络分析 S参数测量&#xff1a;支持全双端口S参数测试&#xf…...

javaSE————网络编程套接字

网络编程套接字~~~~~ 好久没更新啦&#xff0c;蓝桥杯爆掉了&#xff0c;从今天开始爆更嗷&#xff1b; 1&#xff0c;网络编程基础 为啥要有网络编程呢&#xff0c;我们进行网络通信就是为了获取丰富的网络资源&#xff0c;说实话真的很神奇&#xff0c;想想我们躺在床上&a…...

力扣349 == 两个数组交集的两种解法

目录 解法一&#xff1a;利用 Set 特性高效去重 解法二&#xff1a;双重遍历与 Set 去重 方法对比与总结 关键点总结 题目描述 给定两个整数数组 nums1 和 nums2&#xff0c;要求返回它们的交集。输出结果中的每个元素必须是唯一的&#xff0c;且顺序不限。 示例 输入&…...

笔试专题(十)

文章目录 对称之美&#xff08;双指针&#xff09;题解代码 连续子数组最大和&#xff08;线性dp&#xff09;题解代码 最长回文子序列&#xff08;区间dp&#xff09;题解代码 对称之美&#xff08;双指针&#xff09; 题目链接 题解 1. 双指针 2. 用left标记左边的字符串…...

YOLOv12即插即用---RFAConv

1.模块介绍 接受域注意卷积(RFAConv):更聪明地感知空间特征 在传统卷积神经网络中,卷积核参数的共享机制虽有效提升了模型的泛化能力与计算效率,但却忽略了不同空间位置特征在感知范围(即接受域)内的重要性差异。为此,我们提出了一种更具感知能力的模块 —— 接受域注…...

使用datax通过HbaseShell封装writer和reader同步hbase数据到hbase_踩坑_细节总结---大数据之DataX工作笔记008

最近在做大数据相关功能,有个需求,使用datax同步hbase到hbase中,其中还是有很多细节值得记录: 首先来看一下datax的源码中,如果你使用phoenix创建的表,那么 你就需要使用对应的hbase带有sql字样的,reader和writer. 然后如果你使用datax-web来进行测试的,那么,他默认使用的是h…...

Python解决“小D的abc字符变换”问题

小D的“abc”变换问题 问题描述测试样例解题思路代码 问题描述 小D拿到了一个仅由 “abc” 三种字母组成的字符串。她每次操作会对所有字符同时进行以下变换&#xff1a; 将 ‘a’ 变成 ‘bc’ 将 ‘b’ 变成 ‘ca’ 将 ‘c’ 变成 ‘ab’ 小D将重复该操作 k 次。你的任务是输…...

C++学习:六个月从基础到就业——面向对象编程:重载运算符(下)

C学习&#xff1a;六个月从基础到就业——面向对象编程&#xff1a;重载运算符&#xff08;下&#xff09; 本文是我C学习之旅系列的第十三篇技术文章&#xff0c;是面向对象编程中运算符重载主题的下篇。本篇文章将继续深入探讨高级运算符重载技术、特殊运算符、常见应用场景和…...

电压模式控制学习

电压模式控制 在开关电源中&#xff0c;大的可分为三大控制模式&#xff0c;分别是电压模式控制&#xff0c;电流模式控制&#xff0c;迟滞模式控制。今天简要介绍下电压模式控制的优缺点。 原理 架构图如下 如图所示&#xff0c;电压模式控制可以分为三部分&#xff1a;误…...

vue3 Ts axios 封装

vue3 Ts axios 封装 axios的封装 import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosHeaders } from axios import qs from qs import { config } from ./config import { ElMessage } from element-plus// …...

GPT,Bert类模型对比

以下是对 BERT-base、RoBERTa-base、DeBERTa-base 和 DistilBERT-base 四个模型在参数量、训练数据、GPU 内存占用、性能表现以及优缺点方面的对比&#xff1a; 模型参数量与训练数据 模型参数量训练数据量BERT-base110MBookCorpus&#xff08;8亿词&#xff09; 英文维基百科…...

3.Rust + Axum 提取器模式深度剖析

摘要 深入解读 Rust Axum 提取器模式&#xff0c;涵盖内置提取器及自定义实现。 一、引言 在 Rust 的 Web 开发领域&#xff0c;Axum 作为一款轻量级且高效的 Web 框架&#xff0c;为开发者提供了强大的功能。其中&#xff0c;提取器&#xff08;Extractor&#xff09;模式…...

Dify vs n8n vs RAGFlow:2025年AI应用与自动化工作流平台的终极对决

我将为大家整理一份关于 Dify、n8n 和 Ragflow 的最新研究分析,涵盖以下六个方面:功能对比、应用场景、架构设计、集成能力、和使用门槛。我会尽可能引用其官方文档、GitHub 仓库以及社区讨论等权威信息来源。 我整理好后会第一时间通知你查看。 1.Dify、n8n 和 RAGFlow 最新…...

ffmpeg无损转格式的命令行

将ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式转换后.mkv -c:v copy 仅做拷贝视频,不重新编码 -c:a copy 仅做拷贝音频 ,不重新编码...

Flutter 常用命令

1、创建项目 flutter create <项目名称> 示例&#xff1a; flutter create my_app 1.1 参数说明 --org&#xff1a;设置包名&#xff08;默认 com.example&#xff09; flutter create --org com.yourcompany my_app -a/-i&#xff1a;指定语言&#xff08;Kotlin…...