10.23

环境介绍
【1】Apache Avro 1.8;【2】Spring Kafka 1.2;【3】Spring Boot 1.5;【4】Maven 3.5;

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.codenotfound</groupId>
<artifactId>spring-kafka-avro</artifactId>
<version>0.0.1-SNAPSHOT</version>

<name>spring-kafka-avro</name>
<description>Spring Kafka - Apache Avro Serializer Deserializer Example</description>
<url>https://www.codenotfound.com/spring-kafka-apache-avro-serializer-deserializer-example.html</url>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>

<properties>
<java.version>1.8</java.version>

<spring-kafka.version>1.2.2.RELEASE</spring-kafka.version>
<avro.version>1.8.2</avro.version>
</properties>

<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- spring-kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>${spring-kafka.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<version>${spring-kafka.version}</version>
<scope>test</scope>
</dependency>
<!-- avro -->
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>${avro.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- spring-boot-maven-plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- avro-maven-plugin -->
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>${avro.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/resources/avro/</sourceDirectory>
<outputDirectory>${project.build.directory}/generated/avro</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>


二、Avro 文件
【1】Avro 依赖于由使用JSON定义的原始类型组成的架构。对于此示例,我们将使用Apache Avro入门指南中的“用户”模式,如下所示。该模式存储在src / main / resources / avro下的 user.avsc文件中。我这里使用的是 electronicsPackage.avsc。namespace 指定你生成 java 类时指定的 package 路径,name 表时生成的文件。

{"namespace": "com.yd.cyber.protocol.avro",
"type": "record",
"name": "ElectronicsPackage",
"fields": [
{"name":"package_number","type":["string","null"],"default": null},
{"name":"frs_site_code","type":["string","null"],"default": null},
{"name":"frs_site_code_type","type":["string","null"],"default":null},
{"name":"end_allocate_code","type":["string","null"],"default": null},
{"name":"code_1","type":["string","null"],"default": null},
{"name":"aggregat_package_code","type":["string","null"],"default": null}
]
}

【2】Avro附带了代码生成功能,该代码生成功能使我们可以根据上面定义的“用户”模式自动创建Java类。一旦生成了相关的类,就无需直接在程序中使用架构。这些类可以使用 avro-tools.jar 或项目是Maven 项目,调用 Maven Projects 进行 compile 自动生成 electronicsPackage.java 文件:如下是通过 maven 的方式

 

【3】这将导致生成一个 electronicsPackage.java 类,该类包含架构和许多 Builder构造 electronicsPackage对象的方法。

 

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.specific.SpecificDatumWriter;
import org.apache.avro.specific.SpecificRecordBase;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;

/**
* avro序列化类
* @author zzx
* @creat 2020-03-11-19:17
*/
public class AvroSerializer<T extends SpecificRecordBase> implements Serializer<T> {
@Override
public void close() {}

@Override
public void configure(Map<String, ?> arg0, boolean arg1) {}

@Override
public byte[] serialize(String topic, T data) {
if(data == null) {
return null;
}
DatumWriter<T> writer = new SpecificDatumWriter<>(data.getSchema());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
BinaryEncoder binaryEncoder = EncoderFactory.get().directBinaryEncoder(byteArrayOutputStream , null);
try {
writer.write(data, binaryEncoder);
binaryEncoder.flush();
byteArrayOutputStream.close();
}catch (IOException e) {
throw new SerializationException(e.getMessage());
}
return byteArrayOutputStream.toByteArray();
}
}


四、AvroConfig 配置类
Avro 配置信息在 AvroConfig 配置类中,现在,我们需要更改,AvroConfig 开始使用我们的自定义 Serializer实现。这是通过将“ VALUE_SERIALIZER_CLASS_CONFIG”属性设置为 AvroSerializer该类来完成的。此外,我们更改了ProducerFactory 和KafkaTemplate 通用类型,使其指定 ElectronicsPackage 而不是 String。当我们有多个序列化的时候,这个配置文件需要多次需求,添加自己需要序列化的对象。

package com.yd.cyber.web.avro;

/**
* @author zzx
* @creat 2020-03-11-20:23
*/
@Configuration
@EnableKafka
public class AvroConfig {

@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;

@Value("${spring.kafka.producer.max-request-size}")
private String maxRequestSize;

@Bean
public Map<String, Object> avroProducerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG, maxRequestSize);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, AvroSerializer.class);
return props;
}

@Bean
public ProducerFactory<String, ElectronicsPackage> elProducerFactory() {
return new DefaultKafkaProducerFactory<>(avroProducerConfigs());
}

@Bean
public KafkaTemplate<String, ElectronicsPackage> elKafkaTemplate() {
return new KafkaTemplate<>(elProducerFactory());
}
}

 

posted @ 2024-10-23 23:23  混沌武士丞  阅读(13)  评论(0)    收藏  举报