protostuff序列化
在java中,序列化是经常需要使用的,比如对象在网络中传输,那么就必须要序列化后进行传输。而java自带的序列化使用起来虽然方便,但是它序列化后占的体积大,而且不能跨语言,因此在涉及到序列化的时候必然要找到一款高效的序列化框架。在网上查找了一下,发现protostuff使用方便,而且性能比较高,本篇博客简单记录一下ptotostuff如何实现一个序列化和反序列化。
一、需求
1、有一个用户类(Person)和一个地址类(Address),一个人有多个地址
2、person中有部分字段不需要序列化
|- 使用transient修饰即可不进行序列化
3、当对地址单独序列化时,需要定制化序列化,即有用户判断在什么情况下才可以序列化。(比如:当某个字段不可为空时才可以进行序列化)
|- 此种情况可以通过自定义Schema进行实现
4、如果后期序列化的类中新增了字段或删除了字段如何处理,参考 这篇文章, 此处不做处理。
二、实现
1、引入pom文件
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-bom</artifactId>
<version>1.4.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-api</artifactId>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
</dependencies>
注意:主要是引入protostuff-core和protostuff-runtime这2个依赖
2、定义Address类
@Data
@Builder
public class Address {
private String address;
private String phone;
}
3、自定义Address的Schema,用于定制化开发,此处简单实现,当address=null时不可进行序列化
/**
* 自定义Address的Schema,主要是用于定制化开发
* @描述
* @作者 huan
* @时间 2017年12月11日 - 下午9:57:24
*/
public class AddressSchema implements Schema<Address> {
@Override
public String getFieldName(int number) {
String ret = "";
switch (number) {
case 1:
ret = "address";
break;
case 2:
ret = "phone";
default:
break;
}
return ret;
}
@Override
public int getFieldNumber(String name) {
if ("address".equals(name)) {
return 1;
} else if ("phone".equals(name)) {
return 2;
}
return 0;
}
@Override
public boolean isInitialized(Address message) {
if (null != message.getAddress()) {
return true;
}
return false;
}
@Override
public Address newMessage() {
return Address.builder().build();
}
@Override
public String messageName() {
return Address.class.getSimpleName();
}
@Override
public String messageFullName() {
return Address.class.getName();
}
@Override
public Class<? super Address> typeClass() {
return Address.class;
}
@Override
public void mergeFrom(Input input, Address message) throws IOException {
while (true) {
int number = input.readFieldNumber(this);
switch (number) {
case 0:
return;
case 1:
message.setAddress(input.readString());
break;
case 2:
message.setPhone(input.readString());
break;
default:
input.handleUnknownField(number, this);
}
}
}
@Override
public void writeTo(Output output, Address message) throws IOException {
if (message.getAddress() == null) {
throw new UninitializedMessageException(message, this);
}
output.writeString(1, message.getAddress(), false);
if (null != message.getPhone()) {
output.writeString(2, message.getPhone(), false);
}
}
}
注意:此处如果不了解,可以先了解一下protobuff,了解一下.proto文件的写法。
此处做了一个简单的判断,当address==null时,不可进行序列化
4、Person类的开发
@Data
@Builder
public class Person {
private String name;
private Integer age;
private transient String password;
private List<Address> address;
}
注意: 1、Person类包含一个Address的列表
2、注意password字段前面有一个transient,这个表示不进行序列化
3、@Tag注解可以用于标记字段的顺序号,但是一个类中如果要用则建议都使用
4、上方是 官网 给出的一个警告,大致意思是:如果你想在一个非静态的内部类上使用@Tag注解,那么最好将这个非静态的内部类改成静态的内部类。
5、编写测试代码
6、查看结果
本文来自博客园,作者:huan1993,转载请注明原文链接:https://www.cnblogs.com/huan1993/p/15416202.html