使用卡夫卡时将Java转换为Avro并返回

使用卡夫卡时将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;

我正在使用融合平台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.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的子类)