使用卡夫卡时将Java转换为Avro并返回
我正在使用融合平台0.9.0.1和kafka avro序列化程序2.0.1。试图将事件发送到kafka并读回,我不知道如何将事件转换回Java对象。我已经阅读了avro和confluent文档,有迹象表明这是可行的,但我看不出有什么好的例子。这是我的代码,当我用Kafkanconsumer阅读它时,我得到了一个GenericData$记录,我的问题是如何将它返回到Java pojo中。我找到了用于序列化对象的这段代码 这是我的密码:使用卡夫卡时将Java转换为Avro并返回,java,apache-kafka,avro,Java,Apache Kafka,Avro,我正在使用融合平台0.9.0.1和kafka avro序列化程序2.0.1。试图将事件发送到kafka并读回,我不知道如何将事件转换回Java对象。我已经阅读了avro和confluent文档,有迹象表明这是可行的,但我看不出有什么好的例子。这是我的代码,当我用Kafkanconsumer阅读它时,我得到了一个GenericData$记录,我的问题是如何将它返回到Java pojo中。我找到了用于序列化对象的这段代码 这是我的密码: import org.apache.avro.Schema;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.reflect.ReflectData;
import org.apache.avro.reflect.ReflectDatumWriter;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.Properties;
/**
* This is a test...
*/
public class KafkaAvroProducerTest {
private static final Logger log = LogManager.getLogger(KafkaAvroProducerTest.class);
@Test
public void produceAndSendAndEvent() throws Exception {
Properties props = new Properties();
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
org.apache.kafka.common.serialization.StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
io.confluent.kafka.serializers.KafkaAvroSerializer.class);
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put("schema.registry.url", "http://localhost:8081");
KafkaProducer producer = new KafkaProducer(props);
log.debug("starting producer");
String topic = "topic11";
Schema schema = ReflectData.get().getSchema(Purchase.class);
Purchase purchase = new Purchase("appStore", 9.99d, DateTime.now().getMillis(), "BRXh2lf9wm");
ReflectDatumWriter<Purchase> reflectDatumWriter = new ReflectDatumWriter<>(schema);
GenericDatumReader<Object> genericRecordReader = new GenericDatumReader<>(schema);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
reflectDatumWriter.write(purchase, EncoderFactory.get().directBinaryEncoder(bytes, null));
GenericRecord avroRecord = (GenericRecord) genericRecordReader.read(null, DecoderFactory.get().binaryDecoder(bytes.toByteArray(), null));
ProducerRecord record = new ProducerRecord<Object, Object>(topic, avroRecord);
Thread producerThread = new Thread(() -> {
try {
while(true) {
log.debug("send a message {}", record);
producer.send(record);
Thread.sleep(2000);
}
}catch(Exception ex) {
log.error("error", ex);
}
});
producerThread.start();
props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "testGroup");
props.put("auto.commit.enable", "false");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "io.confluent.kafka.serializers.KafkaAvroDeserializer");
props.put("schema.registry.url", "http://localhost:8081");
org.apache.kafka.clients.consumer.KafkaConsumer<String, GenericRecord> kafkaConsumer = new KafkaConsumer(props);
kafkaConsumer.subscribe(Collections.singletonList(topic));
Thread consumerThread = new Thread(() -> {
try {
while(true) {
try {
ConsumerRecords<String, GenericRecord> records = kafkaConsumer.poll(1000);
for (ConsumerRecord<String, GenericRecord> record1 : records) {//
log.debug("read - {}", record1.value().getClass());
}
}catch(Exception ex) {
log.error("error", ex);
}
}
}catch(Exception ex) {
log.error("error", ex);
}
});
consumerThread.start();
System.in.read();
}
}
import org.apache.avro.Schema;
导入org.apache.avro.generic.GenericDatumReader;
导入org.apache.avro.generic.GenericRecord;
导入org.apache.avro.io.DecoderFactory;
导入org.apache.avro.io.EncoderFactory;
导入org.apache.avro.reflect.ReflectData;
导入org.apache.avro.reflect.ReflectDatumWriter;
导入org.apache.kafka.clients.consumer.ConsumerRecord;
导入org.apache.kafka.clients.consumer.ConsumerRecords;
导入org.apache.kafka.clients.consumer.KafkaConsumer;
导入org.apache.kafka.clients.producer.KafkaProducer;
导入org.apache.kafka.clients.producer.ProducerConfig;
导入org.apache.kafka.clients.producer.ProducerRecord;
导入org.apache.logging.log4j.LogManager;
导入org.apache.logging.log4j.Logger;
导入org.joda.time.DateTime;
导入org.junit.Test;
导入java.io.ByteArrayOutputStream;
导入java.util.Collections;
导入java.util.Properties;
/**
*这是一个测试。。。
*/
公共类卡夫卡夫罗普罗斯特{
私有静态最终记录器log=LogManager.getLogger(KafkaAvroProducerTest.class);
@试验
public void produceAndSendAndEvent()引发异常{
Properties props=新属性();
props.put(ProducerConfig.KEY\u序列化程序\u类\u配置,
org.apache.kafka.common.serialization.StringSerializer.class);
props.put(ProducerConfig.VALUE\u序列化程序\u类\u配置,
Kafkavroserializer.class);
put(ProducerConfig.BOOTSTRAP\u SERVERS\u CONFIG,“localhost:9092”);
put(“schema.registry.url”http://localhost:8081");
卡夫卡制作人=新卡夫卡制作人(道具);
调试(“启动生产者”);
字符串topic=“topic11”;
Schema Schema=ReflectData.get().getSchema(Purchase.class);
购买=新购买(“appStore”,9.99d,DateTime.now().getMillis(),“BRXh2lf9wm”);
ReflectDatumWriter ReflectDatumWriter=新的ReflectDatumWriter(模式);
GenericDatumReader genericRecordReader=新的GenericDatumReader(模式);
ByteArrayOutputStream字节=新建ByteArrayOutputStream();
reflectDatumWriter.write(购买,EncoderFactory.get().directBinaryEncoder(字节,null));
GenericRecord avroRecord=(GenericRecord)genericRecordReader.read(null,DecoderFactory.get().binaryDecoder(bytes.toByteArray(),null));
产品记录记录=新产品记录(主题,avroRecord);
线程生成器读取=新线程(()->{
试一试{
while(true){
调试(“发送消息{}”,记录);
制作人。发送(记录);
《睡眠》(2000年);
}
}捕获(例外情况除外){
日志错误(“错误”,ex);
}
});
producerThread.start();
props=新属性();
put(“bootstrap.servers”,“localhost:9092”);
props.put(“group.id”、“testGroup”);
props.put(“auto.commit.enable”、“false”);
put(“key.deserializer”、“org.apache.kafka.common.serialization.StringDeserializer”);
put(“value.deserializer”、“io.confluent.kafka.serializer.KafkaAvroDeserializer”);
put(“schema.registry.url”http://localhost:8081");
org.apache.kafka.clients.consumer.KafkaConsumer KafkaConsumer=新卡夫卡消费者(道具);
kafkaConsumer.subscribe(Collections.singletonList(topic));
线程使用者读取=新线程(()->{
试一试{
while(true){
试一试{
消费者记录记录=kafkaConsumer.poll(1000);
对于(消费者记录记录1:记录){//
debug(“read-{}”,record1.value().getClass());
}
}捕获(例外情况除外){
日志错误(“错误”,ex);
}
}
}捕获(例外情况除外){
日志错误(“错误”,ex);
}
});
consumerThread.start();
System.in.read();
}
}
我从未使用过Avro,但看看为什么您不能简单地手动填充POJO
class MyPojo {
public int v1;
public String v2;
}
// copied from your example code
ConsumerRecords<String, GenericRecord> records = kafkaConsumer.poll(1000);
for (ConsumerRecord<String, GenericRecord> record1 : records) {
GenericRecord avroRecord = record1.value();
MyPojo pojo = new MyPojo();
pojo.v1 = (Integer)avroRecord.get("<fieldname1>");
pojo.v2 = (String)avroRecord.get("<fieldname2>");
// process current pojo
}
类MyPojo{
公共INTV1;
公共字符串v2;
}
//从示例代码中复制
消费者记录记录=kafkaConsumer.poll(1000);
对于(消费者记录记录1:记录){
GenericRecord avroRecord=record1.value();
MyPojo pojo=新的MyPojo();
pojo.v1=(整数)avroRecord.get(“”);
pojo.v2=(字符串)avroRecord.get(“”);
//处理当前pojo
}
不确定这是否有意义。如果这样做有效,我会将它移动到构造函数
MyPojo(GenericRecord)
中,就像手动将数据从GenericRecord序列化程序中拉到java类中一样。。。既然可以让反射库为您编写,为什么还要手动编写呢
对于自动转换为注册的java类型,您将看到创建您自己的KafkaAvroDeserializer,它创建通过ReflectDatumReader创建的特定记录,如本stackoverflow帖子中所列。。。
-谢谢!我想我错误地认为avro就像json一样,你可以简单地序列化和反序列化任何pojo。但是我看到的所有avro示例都使用模式和maven插件来生成类(SpecificRecordBase的子类)