1.简介
Avro是一个数据序列化系统,它有以下特性:
(1)丰富的数据结构。
(2)一种紧凑、快速的二进制文件格式。
(3)存放持久化数据的容器文件。
(4)远程过程调用。
(5)支持动态语言、使用schema生成代码。
2.引入pom
在
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.2</version>
</dependency>
下面第一个maven插件可以通过avro的schema文件生成对应的java类,第二个是普通的java编译插件。将这个两个插件加入到
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.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.7</source>
<target>1.7</target>
</configuration>
</plugin>
3.定义schema
avro的schema是json格式的,支持的基本类型有:null,boolean,int,long,float,double,bytes,string。支持的复杂类型有:record,enum,array,map,union,fixed。
定义一个schema文件User.avsc:
{
"namespace": "net.bigdataer.demo.avro",
"type": "record",
"name": "User",
"fields": [
{
"name": "name",
"type": "string",
"doc":"姓名"
},
{
"name": "favorite_number",
"type": [
"int",
"null"
]
},
{
"name": "favorite_color",
"type": [
"string",
"null"
]
}
]
}
一个avsc文件必须要有type和name以及fields。同时此文件定义了namespace,它和name一起确定了文件的全名:net.bigdataer.demo.avro.User。
4.编译schema
有两种方式可以编译avro的schema,一种是使用avro-tools-1.8.2.jar手动编译,一种是使用上面提到的插件在ide中编译。下面分别对这两种方式做说明:
4.1使用avro-tools-1.8.2.jar 编译
编译命令格式如下:
java -jar avro-tools-1.8.2.jar compile schema
比如: java -jar avro-tools-1.8.2.jar compile schema user.avsc
avro-tools这个包提供了很多的工具,比如tojson可以将avro文件转为可视化的json。
4.2 使用maven插件编译
使用上面提到的avro-maven-plugin插件,可以直接在ide中执行package命令就可以编译出对应的java文件。
5.序列化与反序列化
avro序列化文件有两种方式,一种是根据schema生成实体类,另外一种不用生成实体类,只要指定schema,使用GenericRecord当做实体。下面就两种方式分别给出demo:
5.1 使用生成类User
//avro序列化demo
public class AvroWriter {
public static void main(String args[]) throws IOException {
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();
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
dataFileWriter.create(user1.getSchema(), new File("d://logs/users.avro"));
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.append(user3);
dataFileWriter.close();
}
}
使用avro-tools查看生成文件的内容:
java -jar avro-tools-1.8.2.jar tojson users.avro
//avro反序列化demo
public class AvroDeserialize {
public static void main(String args[]) {
DatumReader<User> reader = new SpecificDatumReader<>(User.class);
DataFileReader<User> fileReader = null;
try {
fileReader = new DataFileReader<User>(new File("d://logs/users.avro"), reader);
User user = null;
while (fileReader.hasNext()) {
user = fileReader.next(user);
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果如下图:
5.2使用GenericRecord
//序列化
public class AvroGenericWriter {
public static void main(String args[]) throws IOException {
Schema schema = new Schema.Parser().parse(new File("d://logs/user.avsc"));
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("d://logs/users-generic.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();
}
}
//反序列化
public class AvroGenericReader {
public static void main(String args[]) throws IOException {
Schema schema = new Schema.Parser().parse(new File("d://logs/user.avsc"));
File file = new File("d://logs/users-generic.avro");
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);
}
}
}