Spring Boot 项目中集成 Kafka-03
在 Spring Boot 项目中集成 Kafka 有多种方式,适应不同的应用场景和需求。以下将详细介绍几种常用的集成方法,包括:
- 使用 Spring Kafka (
KafkaTemplate
和@KafkaListener
) - 使用 Spring Cloud Stream 与 Kafka Binder
- 使用 Spring for Apache Kafka Reactive(基于 Reactor)
- 手动配置 Producer 和 Consumer Bean
- 使用 Spring Integration Kafka
- 在测试中使用嵌入式 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.properties
或 application.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
步骤三:编写消息生产者
使用 @EnableBinding
和 Source
接口:
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
步骤三:编写响应式消息生产者
使用 SenderOptions
和 KafkaSender
:
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();}
}
步骤四:编写响应式消息消费者
使用 ReceiverOptions
和 KafkaReceiver
:
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
, KafkaTemplate
和 ConcurrentKafkaListenerContainerFactory
等 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);}
}
优缺点
- 优点:
- 高度自定义,适用于复杂配置需求。
- 可以灵活配置多个
KafkaTemplate
或KafkaListenerContainerFactory
,适应多种场景。
- 缺点:
- 配置较为繁琐,代码量增加。
- 需要深入理解 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 有多种方式,每种方式适用于不同的应用场景和需求:
-
Spring Kafka (
KafkaTemplate
和@KafkaListener
)
适用于大多数常规应用,简单易用,与 Spring 生态系统无缝集成。 -
Spring Cloud Stream 与 Kafka Binder
适用于微服务架构,需处理复杂消息路由与多中间件支持的场景。 -
Spring for Apache Kafka Reactive
适用于需要响应式编程模型、高并发和非阻塞消息处理的应用。 -
手动配置 Producer 和 Consumer Bean
适用于需要高度自定义 Kafka 配置和行为的应用。 -
Spring Integration Kafka
适用于复杂集成场景,需要与其他消息渠道和系统协作的应用。 -
嵌入式 Kafka 在测试中使用
适用于编写集成测试,提升测试效率和稳定性。
根据项目的具体需求,选择最合适的集成方式能够有效提升开发效率,确保应用的稳定性与可扩展性。
相关文章:
Spring Boot 项目中集成 Kafka-03
在 Spring Boot 项目中集成 Kafka 有多种方式,适应不同的应用场景和需求。以下将详细介绍几种常用的集成方法,包括: 使用 Spring Kafka (KafkaTemplate 和 KafkaListener)使用 Spring Cloud Stream 与 Kafka Binder使用 Spring for Apache K…...
如何在2025年创建一个网站:使用US Domain Center和WordPress的终极指南
在本指南中,我们将向你展示如何正确地使用US Domain Center和WordPress创建一个网站。无论你是要启动一个个人博客,还是一个在线商店,我们都会提供简单易懂的步骤指导。无需技术技能 — — 只需按照我们的简单步骤操作,你就能在今…...
LLM 训练中存储哪些矩阵:权重矩阵,梯度矩阵,优化器状态
LLM 训练中存储哪些矩阵 目录 LLM 训练中存储哪些矩阵深度学习中梯度和优化器是什么在 LLM 训练中通常会存储以下矩阵: 权重矩阵:这是模型的核心组成部分。例如在基于 Transformer 架构的 LLM 中,每一层的多头注意力机制和前馈神经网络都会有相应的权重矩阵。以 BERT 模型为…...
【JVM】总结篇之对象内存布局 执行引擎
文章目录 对象内存布局对象的实例化对象的内存布局对象的方问定位 执行引擎 对象内存布局 对象的实例化 new对象流程?(龙湖地产) 对象创建方法,对象的内存分配。(360安全) 1.判断对象对应的类是否加载、链…...
机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型
机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型 目录 机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型1 过拟合和欠拟合1.1 过拟合1.2 欠拟合 2 正则化惩罚2.1 概念2.2 函数2.3 正则化种类 3 K折交叉验证3.1 概念3.2 图片理解3.3 函数导入3.4 参数理解 4 训练模型K折交…...
【图像处理】OpenCv + Python 实现 Photoshop 中的色彩平衡功能
前言 这是使用 python 和 OpenCv 实现的 Photoshop 中色彩平衡功能的代码,可以设置阴影,高光和中间调的色调参数来调整图片的色彩平衡。 参考文章二也有 python 版本的代码实现,虽然中间调的部分貌似没有实现,但是理论部分讲解还…...
基于vue框架的的校园快递管理系统x0xm0(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
系统程序文件列表 项目功能:学生,校园跑腿,快递代取,代取进度,评价信息 开题报告内容 基于Vue框架的校园快递管理系统开题报告 一、研究背景与意义 随着电子商务的蓬勃发展,校园快递业务急剧增长,成为校园生活中不可或缺的一部分。然而&a…...
【Vim Masterclass 笔记05】第 4 章:Vim 的帮助系统与同步练习(L14+L15+L16)
文章目录 Section 4:The Vim Help System(Vim 帮助系统)S04L14 Getting Help1 打开帮助系统2 退出帮助系统3 查看具体命令的帮助文档4 查看帮助文档中的主题5 帮助文档间的上翻、下翻6 关于 linewise7 查看光标所在术语名词的帮助文档8 关于退…...
智能体(Agent)如何具备自我决策能力的机理与实现方法
一、智能体自我决策能力的机理 从人工智能和控制理论的角度看,智能体能够“自我决策”的核心在于其 “感知–认知–行动” 的循环过程,以及在此过程中引入自主学习与自主优化的机制。经过优化与补充,智能体具备自我决策能力的机理可以分解为…...
Redis 数据库源码分析
Redis 数据库源码分析 我们都知道Redis是一个 <key,value> 的键值数据库,其实也就是一个 Map。如果让我来实现这样一个 Map,我肯定是用数组,当一个 key 来的时候,首先进行 hash 运算,接着对数据的 length 取余&…...
vue3 css实现文字输出带光标显示,文字输出完毕,光标消失的效果
Vue实现过程如下: <template><div ><p ref"dom_element" class"typing" :class"{over_fill: record_input_over}"></p></div> </template> <script setup> import {onMounted, ref} from…...
【Leetcode】731. 我的日程安排表 II
文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接🔗 实现一个程序来存放你的日程安排。如果要添加的时间内不会导致三重预订时,则可以存储这个新的日程安排。 当三个日程安排有一些时间上的交叉时(例如三个日程…...
浅谈棋牌游戏开发流程四:核心业务逻辑(二)——房间匹配与对局流程
一、前言:让玩家轻松坐上“牌桌” 在上一篇文章中,我们深入探讨了用户系统与登录流程,了解了如何让“陌生人”转变为游戏中的“正式玩家”。接下来,我们将迈向游戏的核心环节——房间匹配与对局流程。这是玩家实际参与游戏、互动…...
大学生HTML5期末作业 Web前端网页制作 html5+css3+js html+css网页设计 美食 美食模版2个页面
大学生HTML5期末作业 Web前端网页制作 html5css3js htmlcss网页设计 美食 美食模版2个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修…...
Java100道面试题
1.JVM内存结构 1. 方法区(Method Area) 方法区是JVM内存结构的一部分,用于存放类的相关信息,包括: 类的结构(字段、方法、常量池等)。字段和方法的描述,如名称、类型、访问修饰符…...
MySQL 日志简介
总览 MySQL Server 有以下⼏种⽇志,可以记录服务器正在发⽣的活动。 ⽇志类型⽇志信息 ⼀般查询⽇志 (General query log) 已建⽴的客⼾端连接和从客⼾端接收到的语句 错误⽇志 (Error log) mysqld在启动、运⾏或停⽌时遇到的问题 慢查询⽇志 (Slow query log) 执⾏…...
ubuntu清理磁盘
ubuntu清理磁盘脚本: #!/bin/bash#shell脚本用#作注释行,但是第一行的#!/bin/bash例外sudo apt-get clean sudo rm -rf /tmp/* sudo rm -rf /var/cache/*cd /var/log/ sudo du -h -d 1 rm -rf ./*cd ~/.cache sudo du -h -d 1 rm -rf ./*apt…...
鸿蒙APP之从开发到发布的一点心得
引言: 做鸿蒙开发大概有1年左右时间了,从最开始的看官方文档、看B站视频,到后来成功发布两款个人APP(房贷计算极简版、时简时钟 轻喷,谢谢)。简单描述一下里边遇到的坑以及一些经历吧。 学习鸿蒙开发 个…...
C++二十三种设计模式之享元模式
C二十三种设计模式之享元模式 一、组成二、特点三、目的四、缺点五、示例代码 一、组成 抽象享元类:声明操作方法。 具体享元类:使用内部数据和外部数据来实现操作方法。 享元管理者类:创建和管理具体享元对象。 二、特点 1、创建享元对象…...
基于Python的音乐播放器 毕业设计-附源码73733
摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器,用户可以轻松管理自己的音乐库,播放喜爱的音乐,并享受音乐带来的愉悦体验。 首先,我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…...
基于32单片机的智能语音家居
一、主要功能介绍 以STM32F103C8T6单片机为控制核心,设计一款智能远程家电控制系统,该系统能实现如下功能: 1、可通过语音命令控制照明灯、空调、加热器、窗户及窗帘的开关; 2、可通过手机显示和控制照明灯、空调、窗户及窗帘的开…...
【C语言程序设计——入门】C语言入门与基础语法(头歌实践教学平台习题)【合集】
目录😋 ⚙️C语言环境配置:Windows配置C语言环境(超级详细) <第1关:程序改错> 任务描述 相关知识 1. 头文件的引用 2. 基本语法规则 编程要求 测试说明 通关代码 测试结果 <第2关:scanf 函数>…...
基于Springboot的知名作家交流系统
博主介绍:java高级开发,从事互联网行业多年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实…...
服务器数据恢复—离线盘数超过热备盘数导致raidz阵列崩溃的数据恢复
服务器数据恢复环境&故障: 一台配有32块硬盘的服务器在运行过程中突然崩溃不可用。经过初步检测,基本上确定服务器硬件不存在物理故障。管理员重启服务器后问题依旧。需要恢复该服务器中的数据。 服务器数据恢复环境: 1、将服务器中硬盘…...
conda安装及demo:SadTalker实现图片+音频生成高质量视频
1.安装conda 下载各个版本地址:https://repo.anaconda.com/archive/ win10版本: Anaconda3-2023.03-1-Windows-x86_64 linux版本: Anaconda3-2023.03-1-Linux-x86_64 Windows安装 环境变量 conda -V2.配置conda镜像源 安装pip conda…...
内蒙古水系详细很全shp格式arcgis软件无偏移坐标下载后内容测评
标题中的“内蒙古水系详细很全shp格式arcgis软件无偏移坐标”指的是一个地理信息系统(GIS)数据集,该数据集详细记录了内蒙古地区的水系信息,并以ESRI公司的标准矢量数据格式——Shapefile(.shp)进行存储。S…...
RK3588平台开发系列讲解(系统篇)Linux Kconfig的语法
文章目录 一、什么是Kconfig二、config模块三、menuconfig四、menu 和 endmenu五、choice 和 endchoice六、source七、depends on八、default九、help十、逻辑表达式沉淀、分享、成长,让自己和他人都能有所收获!😄 一、什么是Kconfig Kconfig的语法及代码结构非常简单。本博…...
c#使用SevenZipSharp实现压缩文件和目录
封装了一个类,方便使用SevenZipSharp,支持加入进度显示事件。 双重加密压缩工具范例: using SevenZip; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.…...
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
目录😋 任务描述 相关知识 1. 二叉排序树的基本概念 2. 二叉排序树节点结构体定义 3. 创建二叉排序树 4. 判断是否为二叉排序树 5. 递归查找关键字为 6 的结点并输出查找路径 6. 删除二叉排序树中的节点 测试说明 通关代码 测试结果 任务描述 本关任务&a…...
C# 服务生命周期:Singleton、Scoped、Transient
文章目录 1、概念:服务生命周期单例 (Singleton) :作用域 (Scoped) :瞬态 (Transient) : 2、对 Scoped 和 Transient 进一步辨析Scoped 生命周期Transient 生命周期选择哪种生命周期 1、概念:服务生命周期 单例 (Singleton) : 整个应用程序生命周期中只有一个实例被创建并共享…...
如何让用户在网页中填写PDF表格?
在网页中让用户直接填写PDF表格,可以大大简化填写、打印、扫描和提交表单的流程。通过使用复选框、按钮和列表等交互元素,PDF表格不仅让填写过程更高效,还能方便地在电脑或移动设备上访问和提交数据。 以下是在浏览器中显示可填写PDF表单的四…...
w140体育馆使用预约平台的设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
Linux(Ubuntu)下ESP-IDF下载与安装完整流程(4)
接前一篇文章:Linux(Ubuntu)下ESP-IDF下载与安装完整流程(3) 本文主要看参考官网说明,如下: 快速入门 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 Linux 和 macOS 平台工具链的标准设置 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 前边几回讲解了第一步 —— …...
PDF预览插件
PDF预览插件 可用于当前页面弹窗形式查看,可增加一些自定义功能 pdf预览插件 代码块: pdfobject.js <div class="pdfwrap"><div class="item"><h3>笑场</h3><div class="tags"><p>李诞</p><i&…...
【微服务】2、网关
Spring Cloud微服务网关技术介绍 单体项目拆分微服务后的问题 服务地址问题:单体项目端口固定(如黑马商城为8080),拆分微服务后端口各异(如购物车808、商品8081、支付8086等)且可能变化,前端难…...
计算机网络--路由表的更新
一、方法 【计算机网络习题-RIP路由表更新-哔哩哔哩】 二、举个例子 例1 例2...
网络安全抓包
#知识点: 1、抓包技术应用意义 //有些应用或者目标是看不到的,这时候就要进行抓包 2、抓包技术应用对象 //app,小程序 3、抓包技术应用协议 //http,socket 4、抓包技术应用支持 5、封包技术应用意义 总结点:学会不同对象采用…...
字玩FontPlayer开发笔记8 Tauri2文件系统
字玩FontPlayer开发笔记8 Tauri2文件系统 字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 ElementUI开发,源代码: github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer 笔记 字玩目…...
http源码分析
一、HttpURLConnection http连接池源码分析 二、HttpClient 连接池,每个路由最大连接数 三、OkHttp okhttp的连接池与socket连接...
【vim】vim常用操作总结
vim常用操作总结 一,简介二,操作介绍2.1 命令模式2.1.1 删除(剪切)光标所在行2.1.2 复制2.1.3 粘贴2.1.4 跳到行末2.1.5 跳到行首2.1.6 撤销操作 2.2 视图模式2.3 命令模式2.4 编辑模式 三,总结 一,简介 在…...
【学Rust开发CAD】1 环境搭建
文章目录 一、搭建C/C编译环境二、安装Rust三、配置 PATH 环境变量四、验证安装结果五、安装编辑工具 一、搭建C/C编译环境 Rust 的编译工具依赖 C 语言的编译工具,这意味着你的电脑上至少已经存在一个 C 语言的编译环境。如果你使用的是 Linux 系统,往…...
RK3588开发笔记-spi接口调试
目录 前言 一、SPI接口简介 二、原理图连接 三、设备树配置 四、spi调试 五、spi应用软件接口 总结 前言 在嵌入式系统开发中,SPI(Serial Peripheral Interface)接口作为一种同步、全双工、多设备、多主机的通信协议,广泛应用于连接各种外围设备,如ADC、DAC、数据存…...
AlphaPi相关硬件驱动提取
初涉硬件编程,在咸鱼上搞了几块AlphaPi和microbit的板鼓捣了一下,alphapi生态不完善,网上又无任何文档,搞封闭,可玩性实在有限,但貌似相关扩展板是可以插microbit的,于是想把这些扩展版用microb…...
【Unity3D】Text文本文字掉落效果
相关技术:Text、TextMesh、Rigidbody(刚体)、BoxCollider(碰撞体)、TextGenerator、文本网格、文字网格 原理:使用UGUI Text获取其文字的每个字符网格坐标,转世界坐标生成对应的3D文本(TextMesh…...
MySQL内置函数详解
MySQL内置函数详解 1. 字符串函数 1.1 基本字符串处理 -- 字符串长度 SELECT LENGTH(Hello MySQL); -- 返回11-- 字符串大小写转换 SELECT LOWER(HELLO), UPPER(hello); -- 返回 hello, HELLO-- 字符串截取 SELECT SUBSTRING(MySQL Database, 1, 5); -- 返回 MySQL SELEC…...
【网络安全设备系列】9、WAF(Web应用防火墙)
0x00 定义: Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一种设备。 WAF需要部署在Web服务器的前面,串行接入,不仅在硬件性能上要求高,而且不能影响Web服务,所以HA功能、Bypass功能都是必…...
Express 加 sqlite3 写一个简单博客
例图: 搭建 命令: 前提已装好node.js 开始创建项目结构 npm init -y package.json:{"name": "ex01","version": "1.0.0","main": "index.js","scripts": {"test": &q…...
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
目录😋 任务描述 相关知识 1. 带权有向图 2. 图的邻接矩阵 3. 图的邻接表 测试说明 通关代码 测试结果 任务描述 本关任务:编写一个程序实现图的邻接矩阵和邻接表的存储。 相关知识 为了完成本关任务,你需要掌握: 带权有向图…...
基于单片机的直流稳压电源的设计(论文+源码)
1.系统方案设计 在本次直流稳压电源的设计中,其关键指标如下: 系统输入电压220V交流系统输出直流0到12V可调,步进可以达到0.1V电流最大输出可以到2A具有短路保护功能可以通过液晶或者数码管等显示设备显示当前输出电压 2. 电路图...
Golang开发-案例整理汇总
前言 CSDN的文章缺少一个索引所有文章分类的地方,所以手动创建这么一个文章汇总的地方,方便查找。Golang开发经典案例汇总 GoangWeb开发 GolangWeb开发- net/http模块 GolangWeb开发-好用的HTTP客户端httplib(beego) GolangWeb开发- Gin不使用Nginx部署Vue项目 Golang并发开…...