Spring Boot 项目中集成 Kafka-03

在 Spring Boot 项目中集成 Kafka 有多种方式,适应不同的应用场景和需求。以下将详细介绍几种常用的集成方法,包括:

  1. 使用 Spring Kafka (KafkaTemplate@KafkaListener)
  2. 使用 Spring Cloud Stream 与 Kafka Binder
  3. 使用 Spring for Apache Kafka Reactive(基于 Reactor)
  4. 手动配置 Producer 和 Consumer Bean
  5. 使用 Spring Integration Kafka
  6. 在测试中使用嵌入式 Kafka

每种方法都有其特点和适用场景,选择合适的方法能够有效提升开发效率和应用性能。


1. 使用 Spring Kafka (KafkaTemplate@KafkaListener)

这是最常用的 Spring Boot 集成 Kafka 的方式,依赖于 Spring for Apache Kafka 项目,提供了 KafkaTemplate 用于发送消息,以及 @KafkaListener 注解用于接收消息。

步骤一:添加 Maven 依赖

pom.xml 中引入 spring-kafka 依赖:

<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId>
</dependency>

步骤二:配置 application.propertiesapplication.yml

示例 (application.properties):

# Kafka 集群地址
spring.kafka.bootstrap-servers=worker1:9092,worker2:9092,worker3:9092# 生产者配置
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.acks=1
spring.kafka.producer.retries=3
spring.kafka.producer.batch-size=16384
spring.kafka.producer.linger.ms=1# 消费者配置
spring.kafka.consumer.group-id=myGroup
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.enable-auto-commit=true

步骤三:编写消息生产者

使用 KafkaTemplate 发送消息:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;@Service
public class ProducerService {@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;private static final String TOPIC = "topic1";public void sendMessage(String message) {kafkaTemplate.send(TOPIC, message);}
}

步骤四:编写消息消费者

使用 @KafkaListener 接收消息:

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;@Component
public class ConsumerService {@KafkaListener(topics = "topic1", groupId = "myGroup")public void listen(ConsumerRecord<?, ?> record) {System.out.println("Received message: " + record.value());}
}

优缺点

  • 优点
    • 简单易用,快速上手。
    • 与 Spring 生态系统无缝集成。
    • 支持事务、幂等性等高级特性。
  • 缺点
    • 适用于传统的阻塞式应用,若需要响应式编程则不够友好。

2. 使用 Spring Cloud Stream 与 Kafka Binder

Spring Cloud Stream 是一个构建消息驱动微服务的框架,通过 Binder(绑定器)与不同的消息中间件集成。使用 Kafka Binder,可以更加简化 Kafka 与 Spring Boot 的集成。

步骤一:添加 Maven 依赖

pom.xml 中引入 spring-cloud-starter-stream-kafka 依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>

并确保引入 Spring Cloud 的 BOM 以管理版本:

<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR12</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

步骤二:配置 application.yml

spring:cloud:stream:bindings:output:destination: topic1contentType: application/jsoninput:destination: topic1group: myGroupkafka:binder:brokers: worker1:9092,worker2:9092,worker3:9092

步骤三:编写消息生产者

使用 @EnableBindingSource 接口:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
@EnableBinding(Source.class)
public class StreamProducerService {@Autowiredprivate Source source;public void sendMessage(String message) {source.output().send(MessageBuilder.withPayload(message).build());}
}

步骤四:编写消息消费者

使用 @StreamListener 注解:

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.stereotype.Component;@Component
@EnableBinding(Sink.class)
public class StreamConsumerService {@StreamListener(Sink.INPUT)public void handleMessage(String message) {System.out.println("Received message: " + message);}
}

优缺点

  • 优点
    • 高度抽象,减少配置与代码量。
    • 更适合微服务架构,支持绑定多个输入输出。
    • 支持多种消息中间件,易于切换。
  • 缺点
    • 抽象层较高,可能难以实现一些细粒度的自定义配置。
    • 学习曲线较陡,需理解 Binder 和 Channel 的概念。

3. 使用 Spring for Apache Kafka Reactive(基于 Reactor)

对于需要响应式编程的应用,可以使用基于 Reactor 的 Spring Kafka Reactive 进行集成,实现非阻塞的消息处理。

步骤一:添加 Maven 依赖

目前,Spring Kafka 本身并未直接提供响应式支持,但可以结合 Project Reactor Kafka 使用。

引入 Reactor Kafka 依赖:

<dependency><groupId>io.projectreactor.kafka</groupId><artifactId>reactor-kafka</artifactId><version>1.3.11</version>
</dependency>

步骤二:配置 application.yml

kafka:bootstrap-servers: worker1:9092,worker2:9092,worker3:9092producer:key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializerconsumer:group-id: myReactiveGroupkey-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializerauto-offset-reset: earliest

步骤三:编写响应式消息生产者

使用 SenderOptionsKafkaSender

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import reactor.kafka.sender.KafkaSender;
import reactor.kafka.sender.SenderOptions;
import reactor.kafka.sender.SenderRecord;
import reactor.core.publisher.Mono;import java.util.HashMap;
import java.util.Map;@Service
public class ReactiveProducerService {@Value("${kafka.bootstrap-servers}")private String bootstrapServers;@Beanpublic SenderOptions<String, String> senderOptions() {Map<String, Object> props = new HashMap<>();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);return SenderOptions.create(props);}@Beanpublic KafkaSender<String, String> kafkaSender(SenderOptions<String, String> senderOptions) {return KafkaSender.create(senderOptions);}public Mono<Void> sendMessage(String topic, String key, String value) {SenderRecord<String, String, Integer> record = SenderRecord.create(new org.apache.kafka.clients.producer.ProducerRecord<>(topic, key, value),1);return kafkaSender(senderOptions()).send(Mono.just(record)).then();}
}

步骤四:编写响应式消息消费者

使用 ReceiverOptionsKafkaReceiver

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.kafka.receiver.KafkaReceiver;
import reactor.kafka.receiver.ReceiverOptions;
import reactor.kafka.receiver.ReceiverRecord;import java.util.HashMap;
import java.util.Map;@Service
public class ReactiveConsumerService {@Value("${kafka.bootstrap-servers}")private String bootstrapServers;@Value("${kafka.consumer.group-id}")private String groupId;@Beanpublic ReceiverOptions<String, String> receiverOptions() {Map<String, Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");ReceiverOptions<String, String> receiverOptions = ReceiverOptions.create(props);return receiverOptions.subscription(java.util.Collections.singleton("topic1"));}@Beanpublic Flux<ReceiverRecord<String, String>> kafkaFlux(ReceiverOptions<String, String> receiverOptions) {return KafkaReceiver.create(receiverOptions).receive();}public void consumeMessages() {kafkaFlux(receiverOptions()).doOnNext(record -> {System.out.println("Received: " + record.value());record.receiverOffset().acknowledge();}).subscribe();}
}

优缺点

  • 优点
    • 支持响应式编程模型,适用于高并发和非阻塞场景。
    • 更高的资源利用率和吞吐量。
  • 缺点
    • 相较于传统阻塞式,开发复杂度更高。
    • 需要理解 Reactor 和响应式编程的基本概念。

4. 手动配置 Producer 和 Consumer Bean

对于需要更高自定义配置的应用,可以手动配置 ProducerFactory, ConsumerFactory, KafkaTemplateConcurrentKafkaListenerContainerFactory 等 Bean。

步骤一:添加 Maven 依赖

pom.xml 中引入 spring-kafka 依赖:

<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId>
</dependency>

步骤二:编写 Kafka 配置类

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.*;import java.util.HashMap;
import java.util.Map;@Configuration
@EnableKafka
public class KafkaManualConfig {@Value("${kafka.bootstrap-servers}")private String bootstrapServers;@Value("${kafka.consumer.group-id}")private String groupId;// Producer 配置@Beanpublic ProducerFactory<String, String> producerFactory() {Map<String, Object> configProps = new HashMap<>();configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,bootstrapServers);configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class);configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);// 其他自定义配置return new DefaultKafkaProducerFactory<>(configProps);}@Beanpublic KafkaTemplate<String, String> kafkaTemplate() {return new KafkaTemplate<>(producerFactory());}// Consumer 配置@Beanpublic ConsumerFactory<String, String> consumerFactory() {Map<String, Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,bootstrapServers);props.put(ConsumerConfig.GROUP_ID_CONFIG,groupId);props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);// 其他自定义配置return new DefaultKafkaConsumerFactory<>(props);}// KafkaListenerContainerFactory@Beanpublic ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {ConcurrentKafkaListenerContainerFactory<String, String> factory =new ConcurrentKafkaListenerContainerFactory<>();factory.setConsumerFactory(consumerFactory());// 其他自定义配置,如并发数、批量消费等return factory;}
}

步骤三:编写消息生产者和消费者

Producer 示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;@Service
public class ManualProducerService {@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;private static final String TOPIC = "topic1";public void sendMessage(String message) {kafkaTemplate.send(TOPIC, message);}
}

Consumer 示例:

import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;@Component
public class ManualConsumerService {@KafkaListener(topics = "topic1", groupId = "myGroup")public void listen(String message) {System.out.println("Received message: " + message);}
}

优缺点

  • 优点
    • 高度自定义,适用于复杂配置需求。
    • 可以灵活配置多个 KafkaTemplateKafkaListenerContainerFactory,适应多种场景。
  • 缺点
    • 配置较为繁琐,代码量增加。
    • 需要深入理解 Spring Kafka 的配置与使用。

5. 使用 Spring Integration Kafka

Spring Integration 提供了对 Kafka 的集成支持,适用于需要集成多种消息渠道和复杂消息路由的应用。

步骤一:添加 Maven 依赖

pom.xml 中引入 spring-integration-kafka 依赖:

<dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-kafka</artifactId><version>3.3.5.RELEASE</version>
</dependency>

步骤二:编写 Kafka Integration 配置

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter;
import org.springframework.integration.kafka.outbound.KafkaProducerMessageHandler;
import org.springframework.kafka.core.*;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;import java.util.HashMap;
import java.util.Map;@Configuration
public class SpringIntegrationKafkaConfig {@Beanpublic ProducerFactory<String, String> producerFactory() {Map<String, Object> props = new HashMap<>();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"worker1:9092,worker2:9092,worker3:9092");props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class);props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);return new DefaultKafkaProducerFactory<>(props);}@Beanpublic KafkaTemplate<String, String> kafkaTemplate() {return new KafkaTemplate<>(producerFactory());}// 消费者工厂@Beanpublic ConsumerFactory<String, String> consumerFactory() {Map<String, Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"worker1:9092,worker2:9092,worker3:9092");props.put(ConsumerConfig.GROUP_ID_CONFIG,"myGroup");props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);return new DefaultKafkaConsumerFactory<>(props);}// 输入通道@Beanpublic MessageChannel inputChannel() {return new DirectChannel();}// 消费者适配器@Beanpublic KafkaMessageDrivenChannelAdapter<String, String> kafkaMessageDrivenChannelAdapter() {KafkaMessageDrivenChannelAdapter<String, String> adapter =new KafkaMessageDrivenChannelAdapter<>(consumerFactory(), "topic1");adapter.setOutputChannel(inputChannel());return adapter;}// 消费者处理器@Bean@ServiceActivator(inputChannel = "inputChannel")public MessageHandler messageHandler() {return message -> {String payload = (String) message.getPayload();System.out.println("Received message: " + payload);};}// 输出通道@Beanpublic MessageChannel outputChannel() {return new DirectChannel();}// 生产者处理器@Bean@ServiceActivator(inputChannel = "outputChannel")public MessageHandler producerMessageHandler(KafkaTemplate<String, String> kafkaTemplate) {KafkaProducerMessageHandler<String, String> handler =new KafkaProducerMessageHandler<>(kafkaTemplate);handler.setTopicExpressionString("'topic1'");return handler;}
}

步骤三:发送消息到输出通道

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
public class IntegrationProducerService {@Autowiredprivate MessageChannel outputChannel;public void sendMessage(String message) {outputChannel.send(MessageBuilder.withPayload(message).build());}
}

优缺点

  • 优点
    • 强大的消息路由和转换功能,适用于复杂集成场景。
    • 可以与 Spring Integration 的其他模块无缝协作。
  • 缺点
    • 配置复杂,学习成本较高。
    • 对于简单的 Kafka 集成场景,可能显得过于臃肿。

6. 在测试中使用嵌入式 Kafka

在集成测试中,使用嵌入式 Kafka 可以避免依赖外部 Kafka 集群,提升测试效率与稳定性。

步骤一:添加 Maven 依赖

pom.xml 中引入 spring-kafka-test 依赖:

<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka-test</artifactId><scope>test</scope>
</dependency>

步骤二:编写测试类

使用 @EmbeddedKafka 注解启动嵌入式 Kafka:

import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.test.EmbeddedKafkaBroker;
import org.springframework.kafka.test.context.EmbeddedKafka;
import org.springframework.kafka.test.utils.KafkaTestUtils;import java.util.Map;@SpringBootTest
@EmbeddedKafka(partitions = 1, topics = { "topic1" }, brokerProperties = { "listeners=PLAINTEXT://localhost:9092", "port=9092" })
public class KafkaIntegrationTest {@Autowiredprivate EmbeddedKafkaBroker embeddedKafkaBroker;private static Consumer<String, String> consumer;@BeforeAllpublic static void setUp(@Autowired EmbeddedKafkaBroker embeddedKafkaBroker) {Map<String, Object> consumerProps = KafkaTestUtils.consumerProps("testGroup", "true", embeddedKafkaBroker);consumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);DefaultKafkaConsumerFactory<String, String> consumerFactory = new DefaultKafkaConsumerFactory<>(consumerProps);consumer = consumerFactory.createConsumer();embeddedKafkaBroker.consumeFromAnEmbeddedTopic(consumer, "topic1");}@AfterAllpublic static void tearDown() {if (consumer != null) {consumer.close();}}@Testpublic void testSendAndReceive() {// 发送消息// 假设有一个 ProducerService 可以发送消息// producerService.sendMessage("Hello, Kafka!");// 接收消息// Consumer Record 验证逻辑// 可以使用 KafkaTestUtils 来接收消息并断言}
}

优缺点

  • 优点
    • 不依赖外部 Kafka 集群,适合 CI/CD 环境。
    • 提升测试的可重复性与稳定性。
  • 缺点
    • 嵌入式 Kafka 启动较慢,可能影响测试速度。
    • 需要额外配置,测试代码复杂度增加。

总结

在 Spring Boot 中集成 Kafka 有多种方式,每种方式适用于不同的应用场景和需求:

  1. Spring Kafka (KafkaTemplate@KafkaListener)
    适用于大多数常规应用,简单易用,与 Spring 生态系统无缝集成。

  2. Spring Cloud Stream 与 Kafka Binder
    适用于微服务架构,需处理复杂消息路由与多中间件支持的场景。

  3. Spring for Apache Kafka Reactive
    适用于需要响应式编程模型、高并发和非阻塞消息处理的应用。

  4. 手动配置 Producer 和 Consumer Bean
    适用于需要高度自定义 Kafka 配置和行为的应用。

  5. Spring Integration Kafka
    适用于复杂集成场景,需要与其他消息渠道和系统协作的应用。

  6. 嵌入式 Kafka 在测试中使用
    适用于编写集成测试,提升测试效率和稳定性。

根据项目的具体需求,选择最合适的集成方式能够有效提升开发效率,确保应用的稳定性与可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/65298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生物医学信号处理--绪论

前言 参考书籍&#xff1a;刘海龙&#xff0c;生物医学信号处理&#xff0c;化学工业出版社 生物医学信号分类 1、由生理过程自发或者诱发产生的电生理信号和非电生理信号 • 电生理信号&#xff1a;ECG/心电、EEG/脑电、EMG/肌电、 EGG/胃电、 EOG/眼电 • 非电生理信号&am…

unity 播放 序列帧图片 动画

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、方法一&#xff1a;代码控制播放序列帧1、设置图片属性2、创建Image组件3、简单的代码控制4、挂载代码并赋值 二、方法二&#xff1a;直接使用1.Image上添加…

小程序与物联网(IoT)融合:开启智能生活新篇章

一、引言 随着移动互联网技术的飞速发展&#xff0c;小程序作为一种轻量级的应用形式&#xff0c;凭借其无需下载安装、即用即走的特点&#xff0c;迅速渗透到人们生活的各个领域。与此同时&#xff0c;物联网&#xff08;IoT&#xff09;技术也在不断进步&#xff0c;将各种物…

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?

如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能&#xff0c;选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其&#xff0c;在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换&#xff0c;特别方便。VS文件另…

PCL点云库入门——PCL库点云特征之PFH点特征直方图(Point Feature Histograms -PHF)

1、算法原理 PFH点&#xff08;Point Feature Histogram&#xff09;特征直方图的原理涉及利用参数化查询点与邻域点之间的空间差异&#xff0c;并构建一个多维直方图以捕捉点的k邻域几何属性。这个高维超空间为特征表示提供了一个可度量的信息空间&#xff0c;对于点云对应曲面…

5. CSS引入方式

5.1 CSS的三种样式 按照 CSS 样式书写的位置(或者引入的方式)&#xff0c;CSS样式表可以分为三大类&#xff1a; 1.行内样式表&#xff08;行内式&#xff09; 2.内部样式表&#xff08;嵌入式&#xff09; 3. 外部样式表&#xff08;链接式&#xff09; 5.2 内部样式表 …

为什么ip属地一会河南一会江苏

在使用互联网的过程中&#xff0c;许多用户可能会遇到这样一个问题&#xff1a;自己的IP属地一会儿显示为河南&#xff0c;一会儿又变成了江苏。这种现象可能会让人感到困惑&#xff0c;甚至产生疑虑&#xff0c;担心自己的网络活动是否受到了某种影响。为了解答这一疑问&#…

jmeter性能测试例子

目录 一、介绍 二、操作例子 设置线程数 添加同步定时器 添加聚合报告 一、介绍 在软件测试中&#xff0c;一般用jmeter来对接口做性能测试&#xff0c;对对接口进行一个压力的测试。 简述&#xff1a; 在接口的线程中设置线程的数量和时间&#xff0c;添加一个定时器…

PDFelement 特别版

Wondershare PDFelement Pro 是一款非常强大的PDF编辑软件&#xff0c;它允许用户轻松地编辑、转换、创建和管理PDF文件。这个中文特别版的软件具有许多令人印象深刻的功能&#xff0c;PDFelement Pro 提供了丰富的编辑功能&#xff0c;可以帮助用户直接在PDF文件中添加、删除、…

【OpenCV】使用Python和OpenCV实现火焰检测

1、 项目源码和结构&#xff08;转&#xff09; https://github.com/mushfiq1998/fire-detection-python-opencv 2、 运行环境 # 安装playsound&#xff1a;用于播放报警声音 pip install playsound # 安装opencv-python&#xff1a;cv2用于图像和视频处理&#xff0c;特别是…

深入理解Mybatis原理》MyBatis的sqlSessi

sqlSessionFactory 与 SqlSession 正如其名&#xff0c;Sqlsession对应着一次数据库会话。由于数据库会话不是永久的&#xff0c;因此Sqlsession的生命周期也不应该是永久的&#xff0c;相反&#xff0c;在你每次访问数据库时都需要创建它&#xff08;当然并不是说在Sqlsession…

《HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发

随着HarmonyOS NEXT发布&#xff0c;鸿蒙生态日益壮大&#xff0c;广大开发者对于系统化学习平台和课程的需求愈发强烈。近日&#xff0c;华为精心打造的《HarmonyOS第一课》全新上线&#xff0c;集“学、练、考”于一体&#xff0c;凭借多维融合的教学模式与系统课程设置&…

springboot集成整合工作流,activiti审批流,整合实际案例,流程图设计,流程自定义,表单配置自定义,代码demo流程

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;一套完整并且实际运用在多套项目中的案例&#xff0c;满足日常业务流程审批需求。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端…

《探秘计算机视觉与深度学习:开启智能视觉新时代》

《探秘计算机视觉与深度学习&#xff1a;开启智能视觉新时代》 一、追溯起源&#xff1a;从萌芽到崭露头角二、核心技术&#xff1a;解锁智能视觉的密码&#xff08;一&#xff09;卷积神经网络&#xff08;CNN&#xff09;&#xff1a;图像识别的利器&#xff08;二&#xff0…

Vmware安装centos

用来记录自己安装的过程 一、创建虚拟机安装centos镜像 点击完成后&#xff0c;等待一会会进入centos的系统初始化界面 二、centos初始化配置 三、配置网络 1、虚拟网络编辑器&#xff0c;开启VMnet1、VMnet8的DHCP vmware左上角工具栏&#xff0c;点击【编辑】->【虚拟网…

Unity-Mirror网络框架-从入门到精通之Chat示例

文章目录 前言Chat聊天室Authentication授权ChatAuthenticatorChat示例中的授权流程聊天Chat最后 前言 在现代游戏开发中&#xff0c;网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架&#xff0c;专为多人游戏开发设计。它使得开发者能够轻…

uniapp-vue3 实现, 一款带有丝滑动画效果的单选框组件,支持微信小程序、H5等多端

采用 uniapp-vue3 实现, 是一款带有丝滑动画效果的单选框组件&#xff0c;提供点状、条状的动画过渡效果&#xff0c;支持多项自定义配置&#xff0c;适配 web、H5、微信小程序&#xff08;其他平台小程序未测试过&#xff0c;可自行尝试&#xff09; 可到插件市场下载尝试&…

深度学习GPU服务器推荐:打造高效运算平台

文章来源于百家号&#xff1a;GPU服务器厂家 在深度学习和人工智能领域&#xff0c;一个高性能的GPU服务器是研究和开发工作的关键。今天&#xff0c;我们将为大家推荐一款基于详细硬件配置表的深度学习GPU服务器&#xff0c;它专为高效运算和数据处理而设计。 一、机箱设计 …

78、使用爱芯派2_AX630C开发板 3.2T高有效算力 低功耗 支持AI-ISP真黑光实验

基本思想:使用爱心元智最新的版本开发板进行实验 AX630C、AX620Q 都是 620E 这一代 一、参考这个官方教程,先把代码在本地交叉编译完成 https://github.com/AXERA-TECH/ax620e_bsp_sdk 然后在拷贝到620c设备上 root@ax630c:~/ax620e_bsp_sdk/msp/out/arm64_glibc/bin# ./…