SpringBoot集成kafka-自定义拦截器(可以在拦截器中做记录日志、安全检查等操作)

embedded/2024/10/18 7:45:17/

@TOC

在这里插入图片描述

kafka_6">1、kafka配置类

  • kafka配置类添加@Configuration注解,springboot启动后会自动读取该配置类;
  • 由于在application.yml文件中我们找不到kafak拦截器相关的配置项,因此需要自定义拦截器;
  • 消费者相关配置方法中添加自定义拦截器配置,这样就可以在自定义拦截器中处理个性化业务需求;
  • 配置类中需要注入消费者工厂bean和消费者监听器工厂,以替换kafak内置默认的消费者工厂和消费者监听器工厂。
package com.power.config;import com.power.Inteceptor.CustomConsumerInterceptor;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.config.KafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;import java.util.HashMap;
import java.util.Map;/*** kafka配置类*/
@Configuration
public class KafkaConfig {@Value("${spring.kafka.bootstrap-servers}")private String bootstrapServers;@Value("${spring.kafka.consumer.key-deserializer}")private String keyDeserializer;@Value("${spring.kafka.consumer.value-deserializer}")private String valueDeserializer;/*** 消费者相关配置* @return*/public Map<String,Object> consumerConfigs(){Map<String,Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,bootstrapServers);props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,keyDeserializer);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,valueDeserializer);//添加一个消费者拦截器props.put(ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, CustomConsumerInterceptor.class.getName());return props;}/*** 消费者工厂*/@Beanpublic ConsumerFactory<String,String> consumerFactory(){return new DefaultKafkaConsumerFactory<>(consumerConfigs());}@Beanpublic KafkaListenerContainerFactory<?> ourKafkaListenerContainerFactory(ConsumerFactory<String,String> ourConsumerFactory){ConcurrentKafkaListenerContainerFactory<String,String> listenerContainerFactory = new ConcurrentKafkaListenerContainerFactory<>();listenerContainerFactory.setConsumerFactory(ourConsumerFactory);return listenerContainerFactory;}}

2、自定义拦截器类

package com.power.Inteceptor;import org.apache.kafka.clients.consumer.ConsumerInterceptor;
import org.apache.kafka.clients.consumer.ConsumerRecords;import java.util.Map;/*** 自定义的消费者拦截器*/
public class CustomConsumerInterceptor implements ConsumerInterceptor<String,String> {/*** 在消费消息之前执行* @param record* @return*/@Overridepublic ConsumerRecords onConsume(ConsumerRecords record) {System.out.println("onConsumer方法执行(在消费消息之前执行),record="+record);return record;}/*** 在拿到消息之后,提交offset之前执行该方法* @param offsets*/@Overridepublic void onCommit(Map offsets) {System.out.println("onCommit方法执行(在拿到消息之后,提交offset之前执行该方法),offsets="+offsets);}@Overridepublic void close() {}@Overridepublic void configure(Map<String, ?> configs) {}
}

3、消费者

package com.power.consumer;import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;@Component
public class EventConsumer {@KafkaListener(topics = {"interceptorTopic"}, groupId = "interceptorGroup", containerFactory = "ourKafkaListenerContainerFactory")public void onEvent(ConsumerRecord<String, String> record) {System.out.println("消费者消费消息record = " + record);}
}

4、生产者

package com.power.producer;import com.power.model.User;
import com.power.util.JSONUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Date;@Component
public class EventProducer {@Resourceprivate KafkaTemplate<String,Object> kafkaTemplate;public void sendEvent(){User user = User.builder().id(1).phone("15676767673").birthday(new Date()).build();String userJson = JSONUtils.toJSON(user);kafkaTemplate.send("interceptorTopic","k", userJson);}}

5、实体类(用于发送接收对象消息)

package com.power.model;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {private Integer id;private String phone;private Date birthday;}

6、JSON工具类

package com.power.util;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;public class JSONUtils {private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();public static String toJSON(Object object){try {return OBJECTMAPPER.writeValueAsString(object);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}public static <T> T toBean(String json,Class<T> clazz){try {return OBJECTMAPPER.readValue(json,clazz);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}
}

7、启动类

package com.power;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.kafka.config.KafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;import java.util.Map;@SpringBootApplication
public class Kafka04Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Kafka04Application.class, args);Map<String, ConsumerFactory> beansOfType = context.getBeansOfType(ConsumerFactory.class);beansOfType.forEach((k,v)->{System.out.println(k+" -- "+v);});System.out.println("----------------------------------------------------");Map<String, KafkaListenerContainerFactory> beansOfType2 = context.getBeansOfType(KafkaListenerContainerFactory.class);beansOfType2.forEach((k,v)->{System.out.println(k+" -- "+v);});}}

以下红框内容用于查看SpringBoot启动后注入的类型
在这里插入图片描述
在这里插入图片描述

8、测试类

package com.power;import com.power.producer.EventProducer;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;@SpringBootTest
public class SpringBoot04KafkaBaseApplication {@Resourceprivate EventProducer eventProducer;@Testvoid sendInterceptor(){eventProducer.sendEvent();}}

9、测试

  • 先启动消费者监听
  • 在启动生产者发送消息
  • 测试结果发现,消费者走了我们自定义的拦截器

在这里插入图片描述


http://www.ppmy.cn/embedded/100918.html

相关文章

minio 大视频观看,下载

在线观看 /*** 下载视频文件 fileName文件路径名称 文件路径 BacketName/video/1111.mp4 需要截取桶名后面的路径 video/1111.mp4 video前面不要带/ ** param fileName* param request* param response*/public void play(String fileName, HttpServletRequest request,…

Leetcode 18-四数之和

题解看代码随想录 /* 1.先排序&#xff0c;为了便于使用双指针&#xff0c;复杂度O(logN) 2.固定最小指针a,b,双指针c和d分别从0和len-1向中间移动 从两端向中间移动是为了使得两个数下标不重合&#xff0c;且可以将时间复杂度从双重循环的O(N4)降到O(N3) 3.终止条件&#xff1…

HeidiSQL中一些简单mysql语句的含义(一)

一、创建数据库 #创建一个数据库&#xff0c;这个是数据库的名字叫java62 create database java62; #删除数据库java62 drop database java62; #查看当前mysql里的所有数据库 show databases; #创建student表&#xff0c;varchar括号里的是字符串的长度 create table s…

RabbitMQ高级用法

&#x1f4a5; 该系列属于【SpringBoot基础】专栏&#xff0c;如您需查看其他SpringBoot相关文章&#xff0c;请您点击左边的连接 目录 一、发送者的可靠性 1. 生产者重试机制 2. 生产者确认机制【return和confirm机制】 &#xff08;1&#xff09;开启生产者确认 &#x…

Python策略模式:灵活应对多变的业务逻辑

在软件开发中&#xff0c;我们经常遇到需要根据不同情况执行不同算法或行为的情况。这些场景下&#xff0c;如果直接在代码中嵌入大量的条件判断语句&#xff08;如if-else或switch-case&#xff09;&#xff0c;不仅会使代码变得难以维护&#xff0c;还会降低其扩展性和可复用…

Qt第十六章 多媒体Multimedia

文章目录 多媒体音频播放音频录制音频低延迟音效低级音频播放和录制推送和拉取解码压缩音频到内存与音频处理相关的类 视频播放视频处理低级视频帧录制视频与视频处理相关的类 支持的媒体格式 多媒体 cmakelist 添加Multimedia模块 设备信息查询 #include <QAudioDevice>…

ELK

ELK elk介绍前期准备1、修改主机名2、配置/ect/hosts3、检查防火墙selinux是否关闭4、时钟同步 elasticsearch部署介绍1、安装JAVA包2、解压安装包&#xff0c;修改配置文件 elasticsearch集群部署elaticsearch基础API操作1、RestFul API 格式2、查看节点信息3、查看索引信息和…

【Material-UI】深入了解Radio Group中的useRadioGroup Hook

文章目录 一、什么是useRadioGroup&#xff1f;1.1 Hook的返回值 二、useRadioGroup的基本用法2.1 代码示例2.2 代码解析 三、useRadioGroup的应用场景3.1 动态样式调整3.2 高级交互逻辑 四、使用useRadioGroup的最佳实践4.1 保持代码简洁4.2 结合主题定制4.3 注意无障碍设计 五…