若依系统集成Kafka实现主题监听处理的完整方案
1. 添加依赖
首先在项目的pom.xml中添加Kafka依赖:
xml
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>2.8.1</version>
</dependency>
2. 配置Kafka连接
在application.yml中配置Kafka:
yaml
spring:
kafka:
# Kafka服务器地址
bootstrap-servers: localhost:9092
consumer:
# 消费者组ID
group-id: ruoyi-group
# 自动重置offset为最早
auto-offset-reset: earliest
# 键的反序列化类
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 值的反序列化类
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
producer:
# 键的序列化类
key-serializer: org.apache.kafka.common.serialization.StringSerializer
# 值的序列化类
value-serializer: org.apache.kafka.common.serialization.StringSerializer
listener:
# 监听器类型,单条记录处理
type: single
3. 创建Kafka配置类
kotlin
package com.ruoyi.framework.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
@Configuration
@EnableKafka
public class KafkaConfig {
// 如果需要自定义配置可以在这里添加
}
4. 创建消息生产者服务
typescript
package com.ruoyi.system.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
@Service
public class KafkaProducerService {
private static final Logger log = LoggerFactory.getLogger(KafkaProducerService.class);
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
/**
* 发送消息到指定主题
* @param topic 主题名称
* @param message 消息内容
*/
public void sendMessage(String topic, String message) {
kafkaTemplate.send(topic, message)
.addCallback(
result -> log.info("消息发送成功: topic={}, message={}", topic, message),
ex -> log.error("消息发送失败: topic={}, message={}, error={}", topic, message, ex.getMessage())
);
}
/**
* 发送用户操作日志消息
* @param message 日志消息
*/
public void sendUserLog(String message) {
sendMessage("user-operation-log", message);
}
/**
* 发送系统通知消息
* @param message 通知消息
*/
public void sendSystemNotice(String message) {
sendMessage("system-notice", message);
}
}
5. 创建消息消费者服务
typescript
package com.ruoyi.system.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;
@Service
public class KafkaConsumerService {
private static final Logger log = LoggerFactory.getLogger(KafkaConsumerService.class);
/**
* 监听用户操作日志主题
* @param message 消息内容
*/
@KafkaListener(topics = "user-operation-log", groupId = "ruoyi-group")
public void handleUserOperationLog(String message) {
log.info("接收到用户操作日志: {}", message);
try {
// 这里处理业务逻辑,比如保存到数据库
// userLogService.saveLog(message);
log.info("用户操作日志处理完成: {}", message);
} catch (Exception e) {
log.error("处理用户操作日志失败: {}, error: {}", message, e.getMessage());
}
}
/**
* 监听系统通知主题
* @param message 消息内容
*/
@KafkaListener(topics = "system-notice", groupId = "ruoyi-group")
public void handleSystemNotice(String message) {
log.info("接收到系统通知: {}", message);
try {
// 处理系统通知逻辑
// 比如发送站内信、邮件通知等
log.info("系统通知处理完成: {}", message);
} catch (Exception e) {
log.error("处理系统通知失败: {}, error: {}", message, e.getMessage());
}
}
/**
* 监听多个主题
* @param message 消息内容
*/
@KafkaListener(topics = {"topic1", "topic2", "topic3"}, groupId = "ruoyi-group")
public void handleMultipleTopics(String message) {
log.info("接收到多主题消息: {}", message);
// 处理多个主题的消息
}
}
6. 创建控制器测试接口
less
package com.ruoyi.web.controller.system;
import com.ruoyi.system.service.KafkaProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/kafka")
public class KafkaTestController {
@Autowired
private KafkaProducerService kafkaProducerService;
/**
* 发送测试消息
*/
@PostMapping("/send")
public String sendMessage(@RequestParam String topic, @RequestParam String message) {
kafkaProducerService.sendMessage(topic, message);
return "消息发送成功";
}
/**
* 发送用户操作日志
*/
@PostMapping("/sendUserLog")
public String sendUserLog(@RequestParam String message) {
kafkaProducerService.sendUserLog(message);
return "用户操作日志发送成功";
}
/**
* 发送系统通知
*/
@PostMapping("/sendSystemNotice")
public String sendSystemNotice(@RequestParam String message) {
kafkaProducerService.sendSystemNotice(message);
return "系统通知发送成功";
}
}
7. 批量消息处理
如果需要处理批量消息,可以配置批量监听:
yaml
spring:
kafka:
listener:
type: batch
consumer:
max-poll-records: 50 # 一次拉取最大记录数
fetch-max-wait: 5000 # 拉取最大等待时间
typescript
/**
* 批量消息监听
*/
@KafkaListener(topics = "batch-topic", groupId = "ruoyi-group")
public void handleBatchMessages(List<String> messages) {
log.info("接收到批量消息,数量: {}", messages.size());
for (String message : messages) {
try {
// 处理每条消息
log.info("处理消息: {}", message);
} catch (Exception e) {
log.error("处理消息失败: {}, error: {}", message, e.getMessage());
}
}
}
8. 错误处理和重试机制
typescript
package com.ruoyi.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
@Configuration
public class KafkaListenerConfig {
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(
ConsumerFactory<String, String> consumerFactory) {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
// 设置重试机制
factory.setRetryTemplate(retryTemplate());
// 设置并发数
factory.setConcurrency(3);
return factory;
}
private RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(3000); // 重试间隔3秒
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3); // 最大重试次数
retryTemplate.setBackOffPolicy(backOffPolicy);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
9. 使用示例
在业务服务中使用Kafka:
typescript
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private KafkaProducerService kafkaProducerService;
@Override
public void updateUser(User user) {
// 更新用户逻辑
// ...
// 发送操作日志到Kafka
String logMessage = String.format("用户%s更新了信息: %s",
SecurityUtils.getUsername(), user.getUserName());
kafkaProducerService.sendUserLog(logMessage);
}
}
注意事项
- 确保Kafka服务正常运行
- 根据实际需求调整主题和消费者组配置
- 生产环境需要配置集群和认证信息
- 合理设置消息重试和错误处理机制
- 监控Kafka消息积压情况