本文通过两个示例介绍如何使用avro序列化,反序列数据(Avro的简介请参阅:https://blog.csdn.net/Mathieu66/article/details/105601509)。
我们知道使用Avro序列化、反序列化数据时需要使用数据的schema(schema是对数据结构的描述)。使用时,可以生成schema描述的java类,再基于生成的java类做数据处理,也可以不生成,使用Avro提供的通用数据结构GenericRecord。生成java类的方法官网提供了两种:
1)使用avro提供的工具包手动生成(这与使用Protocol Buffer类似),这种方式略显麻烦,这里不做介绍。
java -jar /path/to/avro-tools-1.9.2.jar compile schema <schema file> <destination>
2)使用maven插件,编译后自动生成。
这里我们先介绍不生成schema Java类的Avro列化反序列化使用方式,之后再介绍需要生成schema Java类的方式。
我们的demo很简单,使用json描述User的基本信息,实例化User,序列化,写出到文件,然后再反序列化将其读出打印在控制台。
首先,我们要定义schema信息User.avsc,位置可自定义(我的在test-avro/src/main/avro目录下,test-avro是项目名)。
namespace是生成schema Java类时使用的。比如这里的User.java将会生成在mvn插件定义的outputDirectory下的com.mathieu.avro路径下。
{"namespace": "com.mathieu.avro",
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type": "string"},
{"name": "favorite_number", "type": ["int", "null"]},
{"name": "favorite_color", "type": ["string", "null"]}
]
}
两种方式均需要引入Avro依赖包
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.9.2</version>
</dependency>
下面开始实操:
1. 不生成schema Java类的方式
package com.mathieu.avro;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import java.io.File;
import java.io.IOException;
/**
* 不生成Schema代码的Avro示例.
*/
public class AvroDemoWithoutCodeGeneration {
public static void main(String[] args) throws IOException {
// 读取Schema
Schema schema = new Schema.Parser().parse(new File("test-avro/src/main/avro/User.avsc"));
// 使用schema创建用户对象.
GenericRecord user1 = new GenericData.Record(schema);
user1.put("name", "Alyssa");
user1.put("favorite_number", 256);
GenericRecord user2 = new GenericData.Record(schema);
user2.put("name", "Ben");
user2.put("favorite_number", 7);
user2.put("favorite_color", "red");
// 序列化并写出到磁盘
File file = new File("test-avro/src/main/resources/users.avro");
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
dataFileWriter.create(schema, file);
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.close();
// 从磁盘反序列化,打印在控制台
DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema);
DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, datumReader);
GenericRecord user = null;
while (dataFileReader.hasNext()) {
user = dataFileReader.next(user);
System.out.println(user);
}
// 运行结果:
// {"name": "Alyssa", "favorite_number": 256, "favorite_color": null}
// {"name": "Ben", "favorite_number": 7, "favorite_color": "red"}
}
}
2.生成Schema Java类的方式
需要添加maven插件
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.9.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
注意:
${project.basedir}/src/main/avro -> User.avsc文件所在路径
${project.basedir}/src/main/java + namespace -> User.java文件坐在路径
在执行 mvn compile 生成User.java文件(第一种方式不会生成User.java文件)。
使用User.java进行数据序列化反序列化的代码:
package com.mathieu.avro;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
import java.io.File;
import java.io.IOException;
/**
* Avro示例(使用CodeGeneration).
*
*/
public class AvroDemoWithCodeGeneration {
public static void main(String[] args) throws IOException {
// 使用三种不同的方式实例化三个user
User user1 = new User();
user1.setName("Alyssa");
user1.setFavoriteNumber(256);
User user2 = new User("Ben", 7, "red");
User user3 = User.newBuilder()
.setName("Charlie")
.setFavoriteColor("blue")
.setFavoriteNumber(null)
.build();
// 序列化user1, user2 and user3 到磁盘
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
File file = new File("test-avro/src/main/resources/users.avro");
dataFileWriter.create(user1.getSchema(), file);
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.append(user3);
dataFileWriter.close();
// 从磁盘反序列化
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = new DataFileReader<User>(file, userDatumReader);
User user = null;
while (dataFileReader.hasNext()) {
user = dataFileReader.next(user);
System.out.println(user);
}
// 运行结果
/* {"name": "Alyssa", "favorite_number": 256, "favorite_color": null}
{"name": "Ben", "favorite_number": 7, "favorite_color": "red"}
{"name": "Charlie", "favorite_number": null, "favorite_color": "blue"}*/
}
}
源码地址:https://gitee.com/mathieu/test-suite.git
参考:http://avro.apache.org/docs/current/gettingstartedjava.html