kafka自定义序列化反序列化
- 0. 问题
- 1. 原因分析
- 2. 解决方法
- 3. 结果测试
0. 问题
最近在学习kafka的时候碰到一个问题,当我尝试使用kafka发生一个pojo对象时,使用如下配置的时候,发现代码报错了,是类型匹配错误:
application.yuml配置如下
###ThymeLeaf配置
spring:
thymeleaf:
#模板的模式,支持 HTML, XML TEXT JAVASCRIPT
mode: HTML5
#编码 可不用配置
encoding: UTF-8
#内容类别,可不用配置
content-type: text/html
#开发配置为false,避免修改模板还要重启服务器
cache: false
#配置模板路径,默认是templates,可以不用配置
prefix: classpath:/templates/
suffix: .html
enabled: true
#国际化
messages:
basename: i18n.login
###########【Kafka集群】###########
kafka:
bootstrap-servers: 192.168.160.131:9092
###########【初始化生产者配置】###########
producer:
# 重试次数
retries: 0
# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
acks: 1
# 批量大小
batch-size: 16384
# 生产端缓冲区大小
buffer-memory: 33554432
# Kafka提供的序列化和反序列化类
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
###########【初始化消费者配置】###########
consumer:
# 是否自动提交offset
enable-auto-commit: true
# 提交offset延时(接收到消息后多久提交offset)
auto-commit-interval: 1000
# 当kafka中没有初始offset或offset超出范围时将自动重置offset
# earliest:重置为分区中最小的offset;
# latest:重置为分区中最新的offset(消费分区中新产生的数据);
# none:只要有一个分区不存在已提交的offset,就抛出异常;
auto-offset-reset: latest
# Kafka提供的序列化和反序列化类
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 默认的消费组ID
group-id: defaultConsumerGroup
# 消费端监听的topic不存在时,项目启动会报错(关掉)
listener:
missing-topics-fatal: false
当我传输一个pojo类时报错:
2021-05-30 15:31:08.159 INFO 6856 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka version: 2.6.0
2021-05-30 15:31:08.159 INFO 6856 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka commitId: 62abe01bee039651
2021-05-30 15:31:08.159 INFO 6856 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka startTimeMs: 1622359868159
2021-05-30 15:31:08.166 INFO 6856 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Cluster ID: Hc_Yc5NaSh6xZSiNbs5Vog
2021-05-30 15:31:08.188 ERROR 6856 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.kafka.common.errors.SerializationException: Can't convert value of class club.jming.pojo.Employee to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer] with root cause
java.lang.ClassCastException: class club.jming.pojo.Employee cannot be cast to class java.lang.String (club.jming.pojo.Employee is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
1. 原因分析
这是由于配置文件(默认也是)使用的序列化和反序列化方法为:
# Kafka提供的序列化和反序列化类
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
# Kafka提供的序列化和反序列化类
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
使用的是字符串序列和反序列化方法,但我们传送的是pojo类,所以会报错ClassCastException
java.lang.ClassCastException: class club.jming.pojo.Employee cannot be cast to class java.lang.String (club.jming.pojo.Employee is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
2. 解决方法
自定义序列化和反序列化类,并在配置文件中指定,注:这里使用了fastjson解析json和序列化json。
自定义的序列化类:
/**
* 自定义序列化
* @author 78289
*/
public class JsonSerializer implements Serializer<Object> {
@Override
public byte[] serialize(String s, Object object) {
return JSON.toJSONBytes(object);
}
}
自定义的反序列化类:
/**
* 自定义反序列化类
* @author 78289
*/
public class JsonDeserializer implements Deserializer<Object> {
@Override
public Object deserialize(String topic, byte[] bytes) {
return JSON.parseObject(bytes,Object.class);
}
}
修改后的配置文件:
###ThymeLeaf配置
spring:
thymeleaf:
#模板的模式,支持 HTML, XML TEXT JAVASCRIPT
mode: HTML5
#编码 可不用配置
encoding: UTF-8
#内容类别,可不用配置
content-type: text/html
#开发配置为false,避免修改模板还要重启服务器
cache: false
#配置模板路径,默认是templates,可以不用配置
prefix: classpath:/templates/
suffix: .html
enabled: true
#国际化
messages:
basename: i18n.login
###########【Kafka集群】###########
kafka:
bootstrap-servers: 192.168.160.131:9092
###########【初始化生产者配置】###########
producer:
# 重试次数
retries: 0
# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
acks: 1
# 批量大小
batch-size: 16384
# 生产端缓冲区大小
buffer-memory: 33554432
# Kafka提供的序列化和反序列化类
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: club.jming.utils.JsonSerializer
###########【初始化消费者配置】###########
consumer:
# 是否自动提交offset
enable-auto-commit: true
# 提交offset延时(接收到消息后多久提交offset)
auto-commit-interval: 1000
# 当kafka中没有初始offset或offset超出范围时将自动重置offset
# earliest:重置为分区中最小的offset;
# latest:重置为分区中最新的offset(消费分区中新产生的数据);
# none:只要有一个分区不存在已提交的offset,就抛出异常;
auto-offset-reset: latest
# Kafka提供的序列化和反序列化类
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: club.jming.utils.JsonDeserializer
# 默认的消费组ID
group-id: defaultConsumerGroup
# 消费端监听的topic不存在时,项目启动会报错(关掉)
listener:
missing-topics-fatal: false
3. 结果测试
2021-05-30 15:37:44.886 INFO 8828 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka version: 2.6.0
2021-05-30 15:37:44.886 INFO 8828 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka commitId: 62abe01bee039651
2021-05-30 15:37:44.886 INFO 8828 --- [nio-8080-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka startTimeMs: 1622360264886
2021-05-30 15:37:44.892 INFO 8828 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Cluster ID: Hc_Yc5NaSh6xZSiNbs5Vog
简单消费-0-topic1-hello_kafka
简单消费-0-topic1-{"gender":1,"birth":1622360264930,"id":1,"email":"782893110@qq.com"}
传输成功!