Protostuff使用入门[通俗易懂]

Protostuff使用入门[通俗易懂]Protostuff The goal of protostuff is to generate a schema whether at compile time or runtime and use that for reading writing to various formats via the provided IO libs Schema A class that

Protostuff

The goal of protostuff is to generate a schema whether at compile-time or runtime and use that for reading/writing to various formats via the provided IO libs.

Schema

A class that encapsulates:

the serialization logic of an object

the deserialization logic of an object

the validation of an object’s required fields

the mapping of an object’s field names to field numbers

the instantiation of the object.

For existing objects, use protostuff-runtime which uses reflection.

示例

User类是个简单的pojo类:

package demo.domain;

import lombok.Data;
import java.util.List;

@Data
public class User {

private String firstName;
private String lastName;
private String email;
private List friends;
}

定义User的序列化逻辑:UserSchema

package demo.serializing;

import demo.domain.User;
import io.protostuff.Input;
import io.protostuff.Output;
import io.protostuff.Schema;
import io.protostuff.UninitializedMessageException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

public class UserSchema implements Schema {


private static final HashMap fieldMap = new HashMap<>();
static {

fieldMap.put("email", 1);
fieldMap.put("firstName", 2);
fieldMap.put("lastName", 3);
fieldMap.put("friends", 4);
}

@Override
public String getFieldName(int number) {

switch (number) {

case 1:
return "email";
case 2:
return "firstName";
case 3:
return "lastName";
case 4:
return "friends";
default:
return null;
}
}

@Override
public int getFieldNumber(String name) {

Integer number = fieldMap.get(name);
return number == null ? 0 : number;
}

@Override
public boolean isInitialized(User message) {

return message.getEmail() != null;
}

@Override
public User newMessage() {

return new User();
}

@Override
public String messageName() {

return User.class.getSimpleName();
}

@Override
public String messageFullName() {

return User.class.getName();
}

@Override
public Class typeClass() {

return User.class;
}

@Override
public void mergeFrom(Input input, User message) throws IOException {

while (true) {

int number = input.readFieldNumber(this);
switch (number) {

case 0:
return;
case 1:
message.setEmail(input.readString());
break;
case 2:
message.setFirstName(input.readString());
break;
case 3:
message.setLastName(input.readString());
break;
case 4:
if (message.getFriends() == null)
message.setFriends(new ArrayList<>());
message.getFriends().add(input.mergeObject(null, this));
break;
default:
input.handleUnknownField(number, this);
}
}
}

@Override
public void writeTo(Output output, User user) throws IOException {

if (user.getEmail() == null)
throw new UninitializedMessageException(user, this);
output.writeString(1, user.getEmail(), false);

if (user.getFirstName() != null)
output.writeString(2, user.getFirstName(), false);

if (user.getLastName() != null)
output.writeString(3, user.getLastName(), false);

if (user.getFriends() != null) {

for (User friend : user.getFriends()) {

if (friend != null)
output.writeObject(4, friend, this, true);
}
}
}

}

序列化和反序列化示例:

package demo;

import demo.domain.User;
import demo.serializing.UserSchema;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import lombok.extern.java.Log;

import java.util.ArrayList;
import java.util.List;

@Log
public class App {


public static void main(String[] args) {

User user1 = new User();
user1.setEmail("1178449100@qq.com");
user1.setFirstName("wenwen");
user1.setLastName("zha");

User user2 = new User();
user2.setEmail("gumengqin@qq.com");
List users = new ArrayList<>();
users.add(user2);
user1.setFriends(users);

Schema schema = new UserSchema();
byte[] data;
data = ProtostuffIOUtil.toByteArray(user1, schema, LinkedBuffer.allocate());
log.info("序列化完成:" + data.length);

User newUser = new User();
ProtostuffIOUtil.mergeFrom(data, newUser, schema);
log.info("反序列化完成:" + newUser);
}

}

RuntimeSchema

使用RuntimeSchema可以不用自定义Schema,省了不少工作。

package demo.serializing;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ProtostuffUtils {


//避免每次序列化都重新申请Buffer空间
private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
//缓存Schema
private static Map, Schema> schemaCache = new ConcurrentHashMap, Schema>();

//序列化方法,把指定对象序列化成字节数组
@SuppressWarnings("unchecked")
public static byte[] serialize(T obj) {

Class clazz = (Class) obj.getClass();
Schema schema = getSchema(clazz);
byte[] data;
try {

data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} finally {

buffer.clear();
}
return data;
}

//反序列化方法,将字节数组反序列化成指定Class类型
public static T deserialize(byte[] data, Class clazz) {

Schema schema = getSchema(clazz);
T obj = schema.newMessage();
ProtostuffIOUtil.mergeFrom(data, obj, schema);
return obj;
}

@SuppressWarnings("unchecked")
private static Schema getSchema(Class clazz) {

Schema schema = (Schema) schemaCache.get(clazz);
if (schema == null) {

schema = RuntimeSchema.getSchema(clazz);
if (schema != null) {

schemaCache.put(clazz, schema);
}
}
return schema;
}
}

重新测试:

package demo;

import demo.domain.User;
import demo.serializing.ProtostuffUtils;
import lombok.extern.java.Log;

import java.util.ArrayList;
import java.util.List;

@Log
public class App {


public static void main(String[] args) {

User user1 = new User();
user1.setEmail("1178449100@qq.com");
user1.setFirstName("wenwen");
user1.setLastName("zha");

User user2 = new User();
user2.setEmail("gumengqin@qq.com");
List users = new ArrayList<>();
users.add(user2);
user1.setFriends(users);


byte[] data = ProtostuffUtils.serialize(user1);
log.info("序列化完成:" + data.length);

User newUser=ProtostuffUtils.deserialize(data,User.class);
log.info("反序列化完成:" + newUser);
}

}
编程小号
上一篇 2025-02-19 09:06
下一篇 2025-03-04 15:11

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/112852.html