avro序列化詳細操作
Intellij 15.0.3
Maven
avro 1.8.0
Avro是一個數據序列化系統。
它提供以下:
1 豐富的數據結構類型
2 快速可壓縮的二進制數據形式
3 存儲持久數據的文件容器
4 遠程過程調用RPC
5 簡單的動態語言結合功能,Avro和動態語言結合後,讀寫數據文件和使用RPC協議都不需要生成代碼,而代碼生成作為一種可選的優化只值得在靜態類型語言中實現。
Avro依賴於模式(Schema)。Avro數據的讀寫操作是很頻繁的,而這些操作都需要使用模式,這樣就減少寫入每個數據資料的開銷,使得序列化快速而又輕巧。這種數據及其模式的自我描述方便於動態腳本語言的使用。
下面介紹如果使用avro進行序列化和反序列化的操作
前置條件:
maven項目
1、在pom.xml中添加avro的依賴包和編譯插件
1.1 配置avro依賴
在dependencies中配置avro的GAV
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.0</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
1.2 在build–>plugins下配置編譯插件
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.0</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.6</source>
<target>1.6</target>
</configuration>
</plugin>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2、定義avro的scheme
Avro scheme是通過JSON形式來定義的,一般以.avsc結尾(maven插件會去指定目錄下獲取.avsc結尾的文件並生成成Java文件)
2.1 在src/main目錄下新建一個avro文件夾
2.2 在src/main/avro目錄下新建一個文件,並保存為user.avsc。文件內容如下:
{"namespace": "cn.md31.avro.test.bean",
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type": "string"},
{"name": "favorite_number", "type": ["int", "null"]},
{"name": "favorite_color", "type": ["string", "null"]}
]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
其中
namespace在java項目中翻譯成包名
name是類名
fields就是配置的屬性
註意:必須配置type為record
2.3 生成User的java文件
avro提供了一個avro-tools包來生成java文件,可以通過下面命令:
java -jar /path/to/avro-tools-1.8.0.jar compile schema <schema file> <destination>
- 1
- 1
在1.2步中,pom文件中配置了插件,所以在maven項目中,我們只需要執行mvn complie 命令就可以自動生成java文件了。
註:插件會自動搜索src/main/avro目錄下的.avsc結尾的文件,並生成java文件到src/main/java包下
因為我們在pom文件中指定了相應目錄:
如果使用Intellij,我們直接執行compile即可:
執行之後會在相應目錄生成User.java文件
1 使用生成的User類初始化User對象
Avro自動生成的User類有三種方式初始化:
1.1 使用構造方法:
User user1 = new User("user1", 10, "red");
1.2 使用setter方法
User user2 = new User();
user2.setName("user2");
user2.setFavoriteNumber(11);
user2.setFavoriteColor("white");
- 1
- 2
1.3 使用build方法
User user3 = User.newBuilder()
.setName("user3")
.setFavoriteNumber(12)
.setFavoriteColor("black")
.build();
整合到produceUsers方法中:
public static List<User> produceUsers() {
List<User> userList = new ArrayList<User>();
// 三種初始化方式
User user1 = new User("user1", 10, "red");
User user2 = new User();
user2.setName("user2");
user2.setFavoriteNumber(11);
user2.setFavoriteColor("white");
User user3 = User.newBuilder()
.setName("user3")
.setFavoriteNumber(12)
.setFavoriteColor("black")
.build();
userList.add(user1);
userList.add(user2);
userList.add(user3);
return userList;
}
2 把User對象序列化到文件中
public static void serializeAvroToFile(List<User> userList, String fileName) throws IOException {
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
dataFileWriter.create(userList.get(0).getSchema(), new File(fileName));
for (User user: userList) {
dataFileWriter.append(user);
}
dataFileWriter.close();
}
在main方法中調用上面兩個方法
public static void main(String[] args) throws IOException {
List<User> userList = produceUsers();
String fileName = "users.avro";
serializeAvroToFile(userList, fileName);
// deserializeAvroFromFile(fileName);
//
// byte[] usersByteArray = serializeAvroToByteArray(userList);
// deserialzeAvroFromByteArray(usersByteArray);
}
執行main方法,會發現在根目錄生成了一個users.avro文件:
3 從文件中反序列化對象
public static void deserializeAvroFromFile(String fileName) throws IOException {
File file = new File(fileName);
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = new DataFileReader<User>(file, userDatumReader);
User user = null;
System.out.println("----------------deserializeAvroFromFile-------------------");
while (dataFileReader.hasNext()) {
user = dataFileReader.next(user);
System.out.println(user);
}
}
執行之後得到結果:
4、序列化對象成byte 數組
public static byte[] serializeAvroToByteArray(List<User> userList) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
dataFileWriter.create(userList.get(0).getSchema(), baos);
for (User user: userList) {
dataFileWriter.append(user);
}
dataFileWriter.close();
return baos.toByteArray();
}
5、從byte數組中反序列化成對象
public static void deserialzeAvroFromByteArray(byte[] usersByteArray) throws IOException {
SeekableByteArrayInput sbai = new SeekableByteArrayInput(usersByteArray);
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = new DataFileReader<User>(sbai, userDatumReader);
System.out.println("----------------deserialzeAvroFromByteArray-------------------");
User readUser = null;
while (dataFileReader.hasNext()) {
readUser = dataFileReader.next(readUser);
System.out.println(readUser);
}
}
avro序列化詳細操作