Spring Boot 项目中集成 Kafka-03

news2025/1/8 14:20:21

在 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 {

    @Autowired
    private 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: topic1
          contentType: application/json
        input:
          destination: topic1
          group: myGroup
      kafka:
        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 {

    @Autowired
    private 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:9092
  producer:
    key-serializer: org.apache.kafka.common.serialization.StringSerializer
    value-serializer: org.apache.kafka.common.serialization.StringSerializer
  consumer:
    group-id: myReactiveGroup
    key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    auto-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;

    @Bean
    public 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);
    }

    @Bean
    public 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;

    @Bean
    public 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"));
    }

    @Bean
    public 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 配置
    @Bean
    public 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);
    }

    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }

    // Consumer 配置
    @Bean
    public 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
    @Bean
    public 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 {

    @Autowired
    private 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 {

    @Bean
    public 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);
    }

    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }

    // 消费者工厂
    @Bean
    public 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);
    }

    // 输入通道
    @Bean
    public MessageChannel inputChannel() {
        return new DirectChannel();
    }

    // 消费者适配器
    @Bean
    public 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);
        };
    }

    // 输出通道
    @Bean
    public 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 {

    @Autowired
    private 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 {

    @Autowired
    private EmbeddedKafkaBroker embeddedKafkaBroker;

    private static Consumer<String, String> consumer;

    @BeforeAll
    public 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");
    }

    @AfterAll
    public static void tearDown() {
        if (consumer != null) {
            consumer.close();
        }
    }

    @Test
    public 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.coloradmin.cn/o/2272603.html

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

相关文章

韩国机场WebGIS可视化集合Google遥感影像分析

目录 前言 一、相关基础数据介绍 1、韩国的机场信息 2、空间数据准备 二、Leaflet叠加Google地图 1、叠加google地图 2、空间点的标记及展示 3、韩国机场空间分布 三、相关成果展示 1、务安国际机场 2、有同类问题的机场 四、总结 前言 12月29日8时57分左右务安国际机…

电子电气架构 --- 设计车载充电机的关键考虑因素

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

python进阶06:MySQL

课后大总结 Day1 一、数据库命令总结 1.连接数据库 连接数据库进入mysql安装目录打开bin文件夹&#xff0c;输入cmd(此命令后无分号)mysql.exe -u root -ppassword命令后输入密码:root 设置密码set passwordpassword("root123"); 查看所有数据库show databases; …

php反序列化原生态 ctfshow练习 字符串逃逸

web262 拿着题审计一下 <?php error_reporting(0); class message{public $from;public $msg;public $to;public $tokenuser;public function __construct($f,$m,$t){$this->from $f;$this->msg $m;$this->to $t;} }$f $_GET[f]; $m $_GET[m]; $t $_GET[t…

探秘前沿科技:RFID 与 NFC,开启智能识别新篇

RFID&#xff08;射频识别&#xff09;与NFC&#xff08;近场通信&#xff09;作为两种基于射频技术的无线通信方式&#xff0c;在现代社会中发挥着越来越重要的作用。尽管它们都具备非接触式识别和通信的能力&#xff0c;但在工作原理、应用场景、技术细节等方面存在着显著的差…

【04】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第四篇安卓APP上架之vivo商店-小米商店,oppo商店,应用宝

【04】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第四篇安卓APP上架之vivo商店-小米商店&#xff0c;oppo商店&#xff0c;应用宝 背景介绍 接第三篇上架华为&#xff0c;由于华为商店较为细致&#xff0c;本篇幅介绍其他4类商店相对简要一点&#xff0c;剩下其他更…

OpenCV计算机视觉 06 图像轮廓检测(轮廓的查找、绘制、特征、近似及轮廓的最小外接圆外接矩形)

目录 图像轮廓检测 轮廓的查找 轮廓的绘制 轮廓的特征 面积 周长 根据面积显示特定轮廓 轮廓的近似 给定轮廓的最小外接圆、外接矩形 外接圆 外接矩形 图像轮廓检测 轮廓的查找 API函数 image, contours, hierarchy cv2.findContours(img, mode, method) 代入参…

ROS2 跨机话题通信问题(同一个校园网账号)

文章目录 写在前面的话校园网模式&#xff08;失败&#xff09;手机热点模式&#xff08;成功&#xff09; 我的实验细节实验验证1、ssh 用户名IP地址 终端控制2、互相 ping 通 IP3、ros2 run turtlesim turtlesim_node/turtle_teleop_key4、ros2 multicast send/receive5、从机…

web3与AI结合-Sahara AI 项目介绍

背景介绍 Sahara AI 于 2023 年创立&#xff0c;是一个 "区块链AI" 领域的项目。其项目愿景是&#xff0c;利用区块链和隐私技术将现有的 AI 商业模式去中心化&#xff0c;打造公平、透明、低门槛的 “协作 AI 经济” 体系&#xff0c;旨在重构新的利益分配机制以及…

【C++】你了解异常的用法吗?

文章目录 Ⅰ. C语言传统的处理错误的方式Ⅱ. C异常概念Ⅲ. 异常的使用1、异常的抛出和匹配原则2、在函数调用链中异常栈展开匹配原则3、异常的重新抛出4、异常安全5、异常规范 Ⅳ. 自定义异常体系Ⅴ. C标准库的异常体系Ⅵ. 异常的优缺点1、异常的优点2、异常的缺点3、总结 Ⅰ. …

Matlab仿真径向受压圆盘光弹图像

Matlab仿真径向受压圆盘光弹图像-十步相移法 主要参数 % 定义圆盘参数 R 15; % 圆盘半径&#xff0c;单位&#xff1a;mm h 5; % 圆盘厚度&#xff0c;单位&#xff1a;mm P 300; % 径向受压载荷大小&#xff0c;单位&#xff…

游戏引擎学习第75天

仓库:https://gitee.com/mrxiao_com/2d_game_2 Blackboard: 处理楼梯通行 为了实现楼梯的平滑过渡和角色的移动控制&#xff0c;需要对楼梯区域的碰撞与玩家的运动方式进行优化。具体的处理方式和遇到的问题如下&#xff1a; 楼梯区域的过渡&#xff1a; 在三维空间中&#x…

算法的学习笔记—不用常规控制语句求 1 到 n 的和

&#x1f600;前言 在算法编程中&#xff0c;有时我们会遇到一些特殊的限制条件&#xff0c;这些限制会迫使我们跳出常规思维。本文讨论的问题就是一个典型案例&#xff1a;在不能使用基本控制语句的情况下&#xff0c;如何求解 1 到 n 的和。这个问题不仅考验编程技巧&#xf…

网络协议安全的攻击手法

1.使用SYN Flood泛洪攻击&#xff1a; SYN Flood(半开放攻击)是最经典的ddos攻击之一&#xff0c;他利用了TCP协议的三次握手机制&#xff0c;攻击者通常利用工具或控制僵尸主机向服务器发送海量的变源端口的TCP SYN报文&#xff0c;服务器响应了这些报文后就会生成大量的半连…

141.《mac m1安装mongodb详细教程》

文章目录 下载从官网下载安装包 下载后双击解压出文件夹安装文件名修改为 mongodb配置data存放位置和日志log的存放位置启动方式一方式二方式二:输入mongo报错以及解决办法 本人电脑 m2 pro,属于 arm 架构 下载 官网地址: mongodb官网 怎么查看自己电脑应该下载哪个版本,输入…

C++ operator = 返回void 会发生什么?

1.operator 正常情况 #include <iostream> using namespace std;class Box { public:Box(double L) : length(L) {}Box(const Box& b){}Box& operator (const Box&){return *this;}public:double length; // 长度 };int main() {Box box1(1.0);Box box2(…

Redis中字符串和列表的区别

在 Redis 中&#xff0c;字符串&#xff08;String&#xff09;和列表&#xff08;List&#xff09;是两种截然不同的数据类型&#xff0c;它们各自有着独特的特点和适用场景。 数据结构 • 字符串&#xff08;String&#xff09;&#xff1a; • 在 Redis 中&#xff0c;字符串…

Elasticsearch JavaRestClient版

文章目录 初始化RestHighLeveClient&#xff08;必要条件&#xff09;索引库操作1.创建索引库&#xff08;4步&#xff09;2.删除索引库&#xff08;3步&#xff09;3.判断索引库是否存在&#xff08;3步&#xff09;4.总结&#xff1a;四步走 文档操作1.创建文档&#xff08;4…

使用Dinky快速提交Flink operator任务

官网地址&#xff1a;K8s集成 | Dinky 1.目前使用版本 Dinky1.2.0、Flink1.18.1、Flink operator0.10.0 2.制作镜像 2.1创建DockerFile ARG FLINK_VERSION1.18.1 FROM flink:${FLINK_VERSION}-scala_2.12 RUN mkdir -p /opt/flink/usrlib COPY commons-cli-1.3.1.jar …

探索数字化展馆:开启科技与文化的奇幻之旅

在科技飞速发展的当下&#xff0c;数字展馆作为一种新兴的展示形式&#xff0c;正逐渐走进大众的视野。数字展馆不仅仅是传统展馆的简单“数字化升级”&#xff0c;更是融合了多媒体、数字化技术以及人机交互等前沿科技的创新产物。 数字展馆借助VR、AR、全息投影等高科技手段&…