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

003 Springboot操作RabbitMQ

Springboot整合RabbitMQ

文章目录

    • Springboot整合RabbitMQ
      • 1.pom依赖
      • 2.yml配置
      • 3.配置队列、交换机
        • 方式一:直接通过配置类配置bean
        • 方式二:消息监听通过注解配置
      • 4.编写消息监听发送测试
      • 5.其他类型交换机配置
        • 1.FanoutExchange
        • 2.TopicExchange
        • 3.HeadersExchange
      • 6.延迟消息处理(TTL)
        • 方式一:ttl配置
        • 方式二:消息发送设置
      • 7.死信队列

1.pom依赖

 <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><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies>

2.yml配置

#配置使用的配置文件
spring:#配置rabbitmqrabbitmq:host: 47.122.26.28 #主机地址port: 5672  #端口号username: xxx #用户名password: xxx #密码virtual-host: my_vhost  #虚拟主机地址#开启消息送达提示publisher-returns: true# springboot.rabbitmq.publisher-confirm 新版本已被弃用,现在使用 spring.rabbitmq.publisher-confirm-type = correlated 实现相同效果publisher-confirm-type: correlatedlistener:  #消息监听配置type: simplesimple:acknowledge-mode: manual #manual手动确认消息  auto没有异常时 进行自动确认 (异常类型 消息重新入队)prefetch: 1 #限制每次发送一条数据。concurrency: 3 #同一个队列启动几个消费者max-concurrency: 3 #启动消费者最大数量#重试策略相关配置retry:# 开启消费者(程序出现异常)重试机制,默认开启并一直重试enabled: true# 最大重试次数max-attempts: 5# 重试间隔时间(毫秒)initial-interval: 3000server:port: 18082address: 127.0.0.1servlet:context-path: /

3.配置队列、交换机

方式一:直接通过配置类配置bean

推送消息时不存在创建队列和交换机

/*** direct模式声明配置*/
@Configuration
public class RabbitDirectConfig {public static final String EXCHANGE_NAME="direct-exchange";public static final String QUEUE_NAME="direct-queue";public static final String BINDING_KEY="change:direct";/*** 声明直连交换机* name:交换机的名称* durable 队列是否持久化* autoDelete:是否自动删除,(当该交换机上绑定的最后一个队列解除绑定后,该交换机自动删除)* argument:其他一些参数*/@Beanpublic DirectExchange directExchange() {return new DirectExchange(EXCHANGE_NAME,false,false,null);}/*** 声明队列*  queue 队列的名称*  durable 队列是否持久化*  exclusive 是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通道不能访问,并且连接自动关闭*  autoDelete 是否自动删除,当最后一个消费者断开连接之后是否自动删除消息。*  arguments 可以设置队列附加参数,设置队列的有效期,消息的最大长度,队列的消息生命周期等等。*/@Beanpublic Queue directQueue() {return new Queue(QUEUE_NAME,false,false,false,null);}/*** 交换机队列绑定*/@Beanpublic Binding springExchangeBindSpringQueue() {return BindingBuilder.bind(directQueue()).to(directExchange()).with(BINDING_KEY);}}
方式二:消息监听通过注解配置

启动时创建队列和交换机

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "direct1-queue",durable = "true"),exchange = @Exchange(value = "direct1-exchange",type = ExchangeTypes.DIRECT,durable = "true"),key = "change1:direct"))

注意:rabbitmq同名的队列只能创建一个,创建多个会报错,推送消息时需确保队列和交换机已存在,

方式一队列和交换机在第一次推送消息时才会自动创建队列和交换机,方式二注解在启动时就会创建

4.编写消息监听发送测试

监听

@Slf4j
@Component
public class RabbitMQListener {@RabbitListener(queues = "direct-queue")@RabbitHandlerpublic void bootMsg(Channel channel, Message message){String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" direct 消费者:'" + message1 + "'");//手动确认该消息try {//消息确认,根据消息序号(false只确认当前一个消息收到,true确认所有比当前序号小的消息(成功消费,消息从队列中删除 ))channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);} catch (IOException e) {log.error("执行异常",e);// 拒绝消息并重新入队channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); }}@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "direct1-queue",durable = "true"),exchange = @Exchange(value = "direct1-exchange",type = ExchangeTypes.DIRECT,durable = "true"),key = "change1:direct"))@RabbitHandlerpublic void bootMsg1(Channel channel, Message message){String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" direct 消费者:'" + message1 + "'");//手动确认该消息try {//消息确认,根据消息序号(false只确认当前一个消息收到,true确认所有比当前序号小的消息(成功消费,消息从队列中删除 ))channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);} catch (IOException e) {log.error("执行异常",e);// 拒绝消息并重新入队channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);}}}

测试

@Slf4j
@SpringBootTest(classes = RabbitProviderApplication.class)
public class RabbitTest {@Autowiredprivate AmqpTemplate amqpTemplate;@Testpublic void directProvider(){String message = "direct模式消息推送。。。。。";/*** 参数分别为,交换机,路由key,消息体*/amqpTemplate.convertAndSend("direct-exchange","change:direct",message);System.out.println(" 消息发送 :'" +message + "'");}@Testpublic void directProvider1(){String message = "direct模式消息推送1。。。。。";/*** 参数分别为,交换机,路由key,消息体*/amqpTemplate.convertAndSend("direct1-exchange","change1:direct",message);System.out.println(" 消息发送1 :'" +message + "'");}}

在这里插入图片描述

5.其他类型交换机配置

1.FanoutExchange
/*** fanout模式声明配置*/
@Configuration
public class RabbitFanoutConfig {public static final String EXCHANGE_NAME="fanout-exchange";public static final String QUEUE_NAME1="fanout-queue1";public static final String QUEUE_NAME2="fanout-queue2";/*** 声明交换机*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange(EXCHANGE_NAME,false,false,null);}/*** 声明队列*/@Beanpublic Queue fanoutQueue1() {return new Queue(QUEUE_NAME1,false,false,false,null);}@Beanpublic Queue fanoutQueue2() {return new Queue(QUEUE_NAME2,false,false,false,null);}/*** 交换机队列绑定*/@Beanpublic Binding springExchangeBindQueue1() {return BindingBuilder.bind(fanoutQueue1()).to(fanoutExchange());}/*** 交换机队列绑定*/@Beanpublic Binding springExchangeBindQueue2() {return BindingBuilder.bind(fanoutQueue2()).to(fanoutExchange());}}

监听

    @RabbitListener(queues = "fanout-queue1")public void fanoutMsg1(Channel channel, Message message) {String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" fanout-queue1 消费者:'" + message1 + "'");}@RabbitListener(queues = "fanout-queue2")public void fanoutMsg2(Channel channel, Message message) {String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" fanout-queue2 消费者:'" + message1 + "'");}

测试

    @Testpublic void fanoutProvider(){String message = "fanout模式消息推送。。。。。";amqpTemplate.convertAndSend("fanout-exchange", "",message);System.out.println(" 消息发送 :'" +message + "'");}

在这里插入图片描述

2.TopicExchange
/*** topic模式声明配置*/
@Configuration
public class RabbitTopicConfig {public static final String EXCHANGE_NAME="topic-exchange";public static final String QUEUE_NAME="topic-queue";public static final String BINDING_KEY="*.orange.#";/*** 声明交换机*/@Beanpublic TopicExchange topicExchange() {return new TopicExchange(EXCHANGE_NAME,false,false,null);}/*** 声明队列*/@Beanpublic Queue topicQueue() {return new Queue(QUEUE_NAME,false,false,false,null);}/*** 交换机队列绑定*/@Beanpublic Binding topicExchangeBindQueue() {return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(BINDING_KEY);}}
    @RabbitListener(queues = "topic-queue")public void topicMsg2(Channel channel, Message message) {String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" topic-queue2 消费者:'" + message1 + "'");}

测试

    @Testpublic void topicProvider(){String message1 = "topic test模式消息推送。。。。。";String message2 = "topic test.aaa模式消息推送。。。。。";amqpTemplate.convertAndSend("topic-exchange", "com.orange.test",message1);amqpTemplate.convertAndSend("topic-exchange", "com.orange.test.aaa",message2);System.out.println(" 消息发送");}

在这里插入图片描述

3.HeadersExchange
/*** headers模式声明配置* 与路由key无关,只需要消息的头参数匹配即可* x-match参数代表是全部匹配还是部分匹配*/
@Configuration
public class RabbitHeadersConfig {public static final String EXCHANGE_NAME="headers-exchange";public static final String QUEUE_NAME="headers-queue";public static final String QUEUE_NAME1="headers-queue1";/*** 声明交换机*/@Beanpublic HeadersExchange headersExchange() {return new HeadersExchange(EXCHANGE_NAME,false,false,null);}/*** 声明队列*/@Beanpublic Queue headersQueue() {return new Queue(QUEUE_NAME,false,false,false,null);}@Beanpublic Queue headersQueue2() {return new Queue(QUEUE_NAME1,false,false,false,null);}/*** 交换机队列绑定(任意匹配)* whereAny 等同于x-match = any*/@Beanpublic Binding headersExchangeBindSpringQueue() {HashMap<String, Object> header = new HashMap<>();header.put("test", "111");header.put("test1", "222");return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAny(header).match();}/*** 交换机队列绑定(全部匹配)* whereAny 等同于x-match = all*/@Beanpublic Binding headersExchangeBindSpringQueue1() {HashMap<String, Object> header = new HashMap<>();header.put("test", "111");header.put("test1", "222");return BindingBuilder.bind(headersQueue2()).to(headersExchange()).whereAll(header).match();}}

发送测试

  @Testpublic void headerProvider(){String param = "headers 模式消息推送。。。。。";MessageProperties messageProperties = new MessageProperties();messageProperties.setContentType("text/plain");messageProperties.setContentEncoding("utf-8");messageProperties.setHeader("test","111");Message message = new Message(param.getBytes(), messageProperties);amqpTemplate.convertAndSend("headers-exchange", null,message);System.out.println(" 消息发送");}

在这里插入图片描述

队列queue任意匹配有数据,queue1全部匹配无数据

headers-queue

在这里插入图片描述

headers-queue1

在这里插入图片描述

消息监听

    @RabbitListener(queues = "headers-queue")public void headersMsg2(Channel channel, Message message) {String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" headers-queue 消费者:'" + message1 + "'");}@RabbitListener(queues = "headers-queue1")public void headers1Msg2(Channel channel, Message message) {String message1 = new String(message.getBody(), StandardCharsets.UTF_8);System.out.println(" headers-queue1 消费者:'" + message1 + "'");}

在这里插入图片描述

6.延迟消息处理(TTL)

  • 第一种是使用普通队列和死信队列来模拟实现延迟的效果。将消息放入一个没有被监听的队列上,设置TTL(一条消息的最大存活时间)为延迟的时间,时间到了没有被消费,直接成为死信,进入死信队列。后监听私信队列来消息消费

  • 第二种是使用rabbitmq官方提供的delayed插件来真正实现延迟队列。

方式一:ttl配置

超时自动删除

/*** rabbitmq的ttl延迟过期时间配置*/
@Configuration
public class RabbitMQTTLConfig {/*** 声明交换机* @return*/@Beanpublic DirectExchange ttlDirectExchange(){return new DirectExchange("ttl-direct-exchange");}/*** 声明队列* @return*/@Beanpublic Queue ttlQueue(){//设置参数Map<String,Object> args = new HashMap<>();//设置ttl过期时间,需设置int值args.put("x-message-ttl",5000);return new Queue("ttl-direct-queue",true,false,false,args);}/*** 绑定队列* @return*/@Beanpublic Binding ttlBingQueue(){return BindingBuilder.bind(ttlQueue()).to(ttlDirectExchange()).with("direct:ttl:key");}}

测试

    @Testpublic void ttlSendMessageTest(){String exchange = "ttl-direct-exchange";String routingKey = "direct:ttl:key";String msg = UUID.randomUUID().toString();//发送并设置amqpTemplate.convertAndSend(exchange,routingKey,msg);System.out.println("消息发送成功====="+msg);}

在这里插入图片描述

方式二:消息发送设置

注释掉x-message-ttl参数,使用普通队列,发送消息时设置过期时间

    @Testpublic void ttlSendMessageTest(){String exchange = "ttl-direct-exchange";String routingKey = "direct:ttl:key";String msg = UUID.randomUUID().toString();//设置过期时间MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setExpiration("5000");message.getMessageProperties().setContentEncoding("UTF-8");return message;}};//发送并设置amqpTemplate.convertAndSend(exchange,routingKey,msg,messagePostProcessor);System.out.println("消息发送成功====="+msg);}

在这里插入图片描述

注意:如果项目中即使用了ttl配置过期时间,有设置了消息过期时间,则执行时以最小的时间为准,ttl过期队列的消息过期会写到死信,而设置方式的普通队列则不会自动写到死信队列

7.死信队列

死信的情况:消息被拒绝,消息过期,队列达到最大长度

死信队列声明

@Configuration
public class RabbitMQDLXConfig {/*** 声明死信交换机* @return*/@Beanpublic DirectExchange dlxDirectExchange(){return new DirectExchange("dlx-direct-exchange");}/*** 声明死信队列* @return*/@Beanpublic Queue dlxQueue(){ ;return new Queue("dlx-direct-queue",true);}/*** 绑定队列* @return*/@Beanpublic Binding dlxBingQueue(){return BindingBuilder.bind(dlxQueue()).to(dlxDirectExchange()).with("direct:dlx:key");}}

过期推送到死信设置

   /*** 声明ttl队列* @return*/@Beanpublic Queue ttlQueue(){//设置参数Map<String,Object> args = new HashMap<>();//设置ttl过期时间,需设置int值args.put("x-message-ttl",5000);args.put("x-max-length",5);//最大长度//消息过期死信队列入队配置args.put("x-dead-letter-exchange","dlx-direct-exchange");//设置死信交换机args.put("x-dead-letter-routing-key","direct:dlx:key");//死信路由key,fanout模式不需要设置路由keyreturn new Queue("ttl-direct-queue",true,false,false,args);}

注意:队列参数修改后,不会重新创建覆盖而是会报错,需要手动删除重新创建,生产环境中则可以通过重新创建一个队列,进行转移

测试

在这里插入图片描述

消息过期进死信队列
在这里插入图片描述

相关文章:

003 Springboot操作RabbitMQ

Springboot整合RabbitMQ 文章目录 Springboot整合RabbitMQ1.pom依赖2.yml配置3.配置队列、交换机方式一&#xff1a;直接通过配置类配置bean方式二&#xff1a;消息监听通过注解配置 4.编写消息监听发送测试5.其他类型交换机配置1.FanoutExchange2.TopicExchange3.HeadersExcha…...

小猿口算脚本

实现原理&#xff1a;安卓adb截图传到电脑&#xff0c;然后用python裁剪获得两张数字图片&#xff0c;使用ddddocr识别数字&#xff0c;比较大小&#xff0c;再用adb命令模拟安卓手势实现>< import os import ddddocr from time import sleep from PIL import Imagedef …...

从 Reno TCP 到 Scalable TCP,HighSpeed TCP

前文 Scalable TCP 如何优化长肥管道 介绍了 Scalable TCP&#xff0c;但联系另一个类似的算法 HighSpeed TCP(简称 HSTCP)&#xff0c;就会看到一个类似从 Reno TCP 经 BIC 到 CUBIC 的路线&#xff0c;但采用了不同的策略。 Reno TCP 经 BIC 到 CUBIC 路线的核心在于 “在长…...

使用Java调用OpenAI API并解析响应:详细教程

使用Java调用OpenAI API并解析响应&#xff1a;详细教程 在现代应用程序中&#xff0c;API调用是一个非常常见的任务。本文将通过一个完整的示例&#xff0c;讲解如何使用Java调用OpenAI的ChatGPT API&#xff0c;并通过ObjectMapper处理JSON响应。本文的示例不仅适用于OpenAI…...

深入学习并发编程中的 synchronized

文章目录 并发编程中的三个问题可见性原子性有序性 了解Java内存模型JMMsynchronized 保证三大特性synchronized 保证原子性synchronized 保证可见性synchronized 保证有序性 synchronized 的特性可重入特性不可中断特性 通过反汇编学习synchronized原理当修饰代码块时当修饰方…...

AMD R9-9950X相比较I9-14900K有哪些提升

AMD R9-9950X相比较I9-14900K有哪些提升&#xff1f;在处理器领域&#xff0c;AMD与英特尔的竞争从未停歇&#xff0c;每一次新品发布都引发业界的高度关注。近日&#xff0c;AMD推出了其新一代桌面级旗舰处理器——Ryzen 9 9950X&#xff08;简称R9-9950X&#xff09;&#xf…...

计算机毕业设计 基于Python的个性化旅游线路推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

总结:Flink之DataStream各API介绍

一、介绍 本文主要是详细介绍 DataStream<T> 类中的各个方法,并给出它们的使用场景。 二、基本方法 getId(): 作用:返回转换操作的唯一标识符。场景:当需要调试或日志记录时,有时候需要知道操作的 ID。getParallelism(): 作用:获取流的并行度。场景:在优化作业时…...

设计一个日志管理系统,支持多级别日志记录

设计一个日志管理系统,支持多级别日志记录 作为一名Python程序软件专家,我经常被问到关于日志管理系统的设计和实现。今天,我将分享一篇关于设计一个日志管理系统,支持多级别日志记录的博文,希望能够帮助大家更好地理解和使用Python语言。 日志管理系统的需求 在软件开…...

Javascript动态规划算法

JavaScript中的动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法。它主要致力于将“合适”的问题拆分成更小的子目标&#xff0c;并通过建立状态转移方程、缓存并复用以往结果以及按…...

Java 循环里怎么删除元素才安全

首先 在 Java 中&#xff0c;当你在循环中遍历集合时&#xff0c;直接删除元素可能会引发 ConcurrentModificationException。为了安全地删除元素&#xff0c;推荐使用 Iterator 来进行删除操作。 以下是使用 Iterator 删除元素的常见模式&#xff1a; import java.util.Arr…...

LabVIEW晶体振荡器自动化测试系统

基于LabVIEW平台的晶体振荡器自动化测试系统解决了传统手工测试晶体振荡器繁琐且易出错的问题。该系统通过高度自动化的测试流程&#xff0c;提高了测试效率和精度&#xff0c;实现了数据的自动采集与处理&#xff0c;适用于电子、通信等领域的晶振测试需求。 项目背景与意义 …...

3.6.xx版本SpringBoot创建基于Swagger接口文档

介绍 基于Swagger构建的JavaAPI文档工具&#xff0c;实现后端功能的测试&#xff0c;并撰写API接口文档。 方法 pom.xml中引入依赖,要注意的是&#xff0c;本依赖使用的SpringBoot版本为3.6.xx <!--Knife4j--><dependency><groupId>com.github.xiaoymin<…...

Oracle 12201非PDBS模式单机部署(静默安装)

一、创建Oracle数据库的用户 groupadd oinstall groupadd dba groupadd asmadmin groupadd asmdba useradd -g oinstall -G dba,asmdba oracle -d /home/oracle passwd oracle二、配置Linux 服务器参数 cat /home/oracle/.bash_profile export ORACLE_HOSTNAMEH_orcle01 expo…...

Python 源码编译安装详解:跨平台指南及完整步骤解析

Python 源码编译安装详解&#xff1a;跨平台指南及完整步骤解析 文章目录 Python 源码编译安装详解&#xff1a;跨平台指南及完整步骤解析一 准备工作1&#xff09;Ubuntu/Debian2&#xff09;CentOS/RHEL3&#xff09;macOS 二 下载 Python 源码三 编译与安装1&#xff09;解压…...

MQTT vs HTTP:谁更适合物联网?

前言 随着物联网&#xff08;IoT&#xff09;技术的飞速发展中&#xff0c;其应用规模和使用场景正在持续扩大&#xff0c;但它关键的流程仍然是围绕数据传输来进行的&#xff0c;因此设备通信协议选择至关重要。 作为两种主要的通信协议&#xff0c;MQTT 协议和 HTTP 协议各…...

小北的技术博客:探索华为昇腾CANN训练营与AI技术创新——Ascend C算子开发能力认证考试(初级)

前言 哈喽哈喽友友们,这里是zyll~(小北)智慧龙阁的创始人及核心技术开发者。在技术的广阔天地里,我专注于大数据与全栈开发,并致力于成为这一领域的新锐力量。通过智慧龙阁这个平台,我期望能与大家分享我的技术心得,共同探索技术的无限可能。 Ascend C编程:小北的技术…...

鸿蒙next开发者第一课02.DevEcoStudio的使用-习题

【习题】DevEco Studio的使用 通过/及格分80/ 满分100 判断题 1. 如果代码中涉及到一些网络、数据库、传感器等功能的开发&#xff0c;均可使用预览器进行预览。F 正确(True)错误(False) 预览器不能进行传感器等特殊功能的开发,需要使用真机开发 2. module.json5文件中的…...

【vue】监听table水平滚动条切换tab后还原位置

有个需求就是切换tab后&#xff0c;原先的table水平滚动条要还原位置&#xff08;如下图&#xff09;&#xff0c;先说下思路&#xff0c;大致就是 切出页面时 把滚动距离保存到Storage 中&#xff0c;切回来时在恢复 直接上代码 首先table ref指定一下ref"jtable" …...

C#使用PdfSharp生成PDF文件实例详解

许多项目开发中需要生成PDF, 常规办法使用官方提供的Microsoft.Office.Interop.Worddll插件,但是这种方法需要完全安装OFFICE,另外版本不一致还会出现很多错误。一般不推荐使用。 下面介绍几种巧妙的用法,定能事半功倍。 本文使用PDFsharp完成功能。 PDFsharp一款开源的…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...