如何自定义方法Serializer完成 String、List、Map等动态数据序列化呢?
Serializer 接口
package com.john.netty.learn.ch08.core;
import org.jboss.netty.buffer.ChannelBuffer;
public interface Serializer {
public void writeToBuffer(ChannelBuffer writeChanneBuffer);public void readByBuffer(ChannelBuffer channelBuffer) throws InstantiationException, IllegalAccessException;
}
AbstractSerializer
String序列化&反序列化: 长度+byte流 (注意:这里支持Null 通过-1区分)
public AbstractSerializer writeString(String value) {
if (value == null) {
writeBuffer.writeShort(-1);
return this;
}
byte[] bytes = value.getBytes(CHARSET);
writeBuffer.writeShort(bytes.length);
if (bytes.length > 0) {
writeBuffer.writeBytes(bytes);
}
return this;
}
public String readString() {
short length = this.readBuffer.readShort();
if (length == -1) {
return null;
}
if (length == 0) {
return "";
}
byte[] bytes = new byte[length];readBuffer.readBytes(bytes);
return new String(bytes);
}
Date序列化&反序列化: (注意:这里支持Null 通过0区分)
public AbstractSerializer writeDate(Date date) {
if (date == null) {
writeBuffer.writeLong(0);
return this;
}
writeBuffer.writeLong(date.getTime());
return this;
}
public Date readDate() {
long l = readBuffer.readLong();
if (l == 0) {
return null;
}
return new Date(l);
}
List序列化&反序列化: Size+Object byte流 (注意:这里支持Null 通过-1区分)
public <T> AbstractSerializer writeList(List<T> list) {
if (isEmpty(list)) {
writeBuffer.writeShort(list == null ? -1 : 0);
return this;
}
writeBuffer.writeShort((short) list.size());
for (T item : list) {
writeObject(item);
}
return this;
}
public <T> List<T> readList(Class<T> clz) throws InstantiationException, IllegalAccessException {
short s = readBuffer.readShort();
if (s == -1) {
return null;
}
List<T> list = new ArrayList<>(s);
for (int i = 0; i < s; i++) {
list.add(readObject(clz));
}
return list;
}
Map序列化&反序列化: size + [Key Object & Value Object] (注意:这里支持Null 通过-1区分)
public <K, V> AbstractSerializer writeMap(Map<K, V> map) {
if (isEmpty(map)) {
writeBuffer.writeShort(map == null ? -1 : 0);
return this;
}
writeBuffer.writeShort((short) map.size());
for (Entry<K, V> entry : map.entrySet()) {
this.writeObject(entry.getKey());
this.writeObject(entry.getValue());
}
return this;
}
public <K, V> Map<K, V> readMap(Class<K> keyClz, Class<V> valClz)
throws InstantiationException, IllegalAccessException {
short s = readBuffer.readShort();
if (s == -1) {
return null;
}
Map<K, V> maps = new HashMap<>(s);
for (int i = 0; i < s; i++) {
maps.put(readObject(keyClz), readObject(valClz));
}
return maps;
}
AbstractSerializer 完成代码:
package com.john.netty.learn.ch08.core;
import java.lang.reflect.Array;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.netty.buffer.ChannelBuffer;
public abstract class AbstractSerializer implements Serializer {
public static final Charset CHARSET = Charset.forName("UTF-8");
protected ChannelBuffer writeBuffer;
protected ChannelBuffer readBuffer;
protected AbstractSerializer() {
}
public void readByBuffer(ChannelBuffer channelBuffer) throws InstantiationException, IllegalAccessException {
this.readBuffer = channelBuffer;
this.read();
}
public byte[] getSerializerBytes() {
byte[] bytes = new byte[writeBuffer.writerIndex()];
writeBuffer.readBytes(bytes);
writeBuffer.clear();
return bytes;
}
public int readIntValue() {
return readBuffer.readInt();
}
public Integer readInt() {
byte b = readBuffer.readByte();
if (b == 0) {
return null;
}
return readBuffer.readInt();
}
public String readString() {
short length = this.readBuffer.readShort();
if (length == -1) {
return null;
}
if (length == 0) {
return "";
}
byte[] bytes = new byte[length];
readBuffer.readBytes(bytes);
return new String(bytes);
}
public long readLongValue() {
return readBuffer.readLong();
}
public Long readLong() {
byte b = readBuffer.readByte();
if (b == 0) {
return null;
}
return readBuffer.readLong();
}
public Date readDate() {
long l = readBuffer.readLong();
if (l == 0) {
return null;
}
return new Date(l);
}
public <T> List<T> readList(Class<T> clz) throws InstantiationException, IllegalAccessException {
short s = readBuffer.readShort();
if (s == -1) {
return null;
}
List<T> list = new ArrayList<>(s);
for (int i = 0; i < s; i++) {
list.add(readObject(clz));
}
return list;
}
public <K, V> Map<K, V> readMap(Class<K> keyClz, Class<V> valClz)
throws InstantiationException, IllegalAccessException {
short s = readBuffer.readShort();
if (s == -1) {
return null;
}
Map<K, V> maps = new HashMap<>(s);
for (int i = 0; i < s; i++) {
maps.put(readObject(keyClz), readObject(valClz));
}
return maps;
}
public <T> T readObject(Class<T> clz) throws InstantiationException, IllegalAccessException {
if (clz == Integer.class) {
return (T) readInt();
}
if (clz == Long.class) {
return (T) readLong();
}
if (clz == String.class) {
return (T) this.readString();
}
if (clz == Date.class) {
return (T) this.readDate();
}
if (List.class.isAssignableFrom(clz)) {
return (T) this.readList(clz);
}
if (Serializer.class.isAssignableFrom(clz)) {
byte b = this.readBuffer.readByte();
if (b == 0) {
return null;
}
Object obj = clz.newInstance();
((Serializer) obj).readByBuffer(readBuffer);
return (T) obj;
}
throw new IllegalArgumentException("不可序列化的类型:" + clz.getName());
}
/**
* 写入目标buff
*
* @param buffer
* @return
*/
public void writeToBuffer(ChannelBuffer writeChanneBuffer) {
this.writeBuffer = writeChanneBuffer;
this.write();
}
public ChannelBuffer writeToLocalBuff() {
writeBuffer = BufferFactory.getBuffer();
writeToBuffer(writeBuffer);
return writeBuffer;
}
public AbstractSerializer writeByte(byte value) {
writeBuffer.writeByte(value);
return this;
}
public AbstractSerializer writeByte(Byte value) {
if (value == null) {
writeBuffer.writeByte(0);
return this;
}
writeBuffer.writeByte(1);
writeBuffer.writeByte(value);
return this;
}
public AbstractSerializer writeShort(short value) {
writeBuffer.writeShort(value);
return this;
}
public AbstractSerializer writeShort(Short value) {
if (value == null) {
writeBuffer.writeByte(0);
return this;
}
writeBuffer.writeByte(1);
writeBuffer.writeShort(value);
return this;
}
public AbstractSerializer writeInt(int value) {
writeBuffer.writeInt(value);
return this;
}
public AbstractSerializer writeInt(Integer value) {
if (value == null) {
writeBuffer.writeByte(0);
return this;
}
writeBuffer.writeByte(1);
writeBuffer.writeInt(value);
return this;
}
public AbstractSerializer writeDouble(Double value) {
if (value == null) {
writeBuffer.writeByte(0);
return this;
}
writeBuffer.writeByte(1);
writeBuffer.writeDouble(value);
return this;
}
public AbstractSerializer writeDouble(double value) {
writeBuffer.writeDouble(value);
return this;
}
public AbstractSerializer writeLong(Long value) {
if (value == null) {
writeBuffer.writeByte(0);
return this;
}
writeBuffer.writeByte(1);
writeBuffer.writeLong(value);
return this;
}
public AbstractSerializer writeLong(long value) {
writeBuffer.writeLong(value);
return this;
}
public AbstractSerializer writeString(String value) {
if (value == null) {
writeBuffer.writeShort(-1);
return this;
}
byte[] bytes = value.getBytes(CHARSET);
writeBuffer.writeShort(bytes.length);
if (bytes.length > 0) {
writeBuffer.writeBytes(bytes);
}
return this;
}
public AbstractSerializer writeDate(Date date) {
if (date == null) {
writeBuffer.writeLong(0);
return this;
}
writeBuffer.writeLong(date.getTime());
return this;
}
public <T> AbstractSerializer writeList(List<T> list) {
if (isEmpty(list)) {
writeBuffer.writeShort(list == null ? -1 : 0);
return this;
}
writeBuffer.writeShort((short) list.size());
for (T item : list) {
writeObject(item);
}
return this;
}
public <K, V> AbstractSerializer writeMap(Map<K, V> map) {
if (isEmpty(map)) {
writeBuffer.writeShort(map == null ? -1 : 0);
return this;
}
writeBuffer.writeShort((short) map.size());
for (Entry<K, V> entry : map.entrySet()) {
this.writeObject(entry.getKey());
this.writeObject(entry.getValue());
}
return this;
}
public AbstractSerializer writeArray(Array array) {
if (isEmpty(array)) {
writeBuffer.writeShort(array == null ? -1 : 0);
return this;
}
int length = Array.getLength(array);
writeBuffer.writeShort(length);
for (int i = 0; i < length; i++) {
this.writeObject(Array.get(array, i));
}
return this;
}
private boolean isEmpty(Array array) {
return array == null || Array.getLength(array) == 0;
}
public AbstractSerializer writeObject(Object object) {
if (object instanceof Array) {
writeArray((Array) object);
return this;
}
if (object instanceof Byte) {
this.writeByte((Byte) object);
return this;
}
if (object instanceof Short) {
this.writeShort((Short) object);
return this;
}
if (object instanceof Integer) {
this.writeInt((Integer) object);
return this;
}
if (object instanceof Date) {
this.writeDate((Date) object);
return this;
}
if (object instanceof String) {
this.writeString((String) object);
return this;
}
if (object instanceof List) {
this.writeList((List) object);
return this;
}
if (object instanceof Map) {
this.writeMap((Map) object);
return this;
}
if (object instanceof Serializer) {
if (object == null) {
writeByte((byte) 0);
return this;
}
writeByte((byte) 1);
((Serializer) object).writeToBuffer(writeBuffer);
return this;
}
throw new IllegalArgumentException("不可序列化的类型:" + object.getClass());
}
/**
* 反序列化具体实现
*/
protected abstract void read() throws InstantiationException, IllegalAccessException;
/**
* 序列化具体实现
*/
protected abstract void write();
private boolean isEmpty(Map map) {
return map == null || map.isEmpty();
}
private boolean isEmpty(List<?> list) {
return list == null || list.isEmpty();
}
}
测试:
MainSerializer
package com.john.netty.learn.ch08;
import java.util.Arrays;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
public class MainSerializer {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Player player = new Player();
player.setId(null);
player.setAge(10);
player.setName("John hao");
Skill skill = new Skill();
skill.setType(1);
skill.setDesc("Fly");
player.addSkill(skill);
skill = new Skill();
skill.setType(2);
skill.setDesc("Run");
player.addSkill(skill);
player.addScope("Fly", 1);
player.addScope("Run", 2);
player.addScope("Unkown", 3);
player.writeToLocalBuff();
byte[] bytes = player.getSerializerBytes();
System.out.println(Arrays.toString(bytes));
ChannelBuffer channelBuffer = ChannelBuffers.wrappedBuffer(bytes);
Player player2 = new Player();
player2.readByBuffer(channelBuffer);
System.out.println(player2 + " scopes:" + player2.getScopes());
}
}
Player
package com.john.netty.learn.ch08;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.john.netty.learn.ch08.core.AbstractSerializer;
public class Player extends AbstractSerializer {
private Long id;
private String name;
private int age;
private List<Skill> skills = new ArrayList<>();
private Map<String, Integer> scopes = new HashMap<>();
public Player() {
}
public Map<String, Integer> getScopes() {
return scopes;
}
public void setScopes(Map<String, Integer> scopes) {
this.scopes = scopes;
}
public void addScope(String key, Integer value) {
scopes.put(key, value);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void addSkill(Skill skill) {
skills.add(skill);
}
public List<Skill> getSkills() {
return skills;
}
public void setSkills(List<Skill> skills) {
this.skills = skills;
}
@Override
protected void read() throws InstantiationException, IllegalAccessException {
this.id = this.readLong();
this.name = this.readString();
this.age = this.readIntValue();
this.skills = this.readList(Skill.class);
this.scopes = this.readMap(String.class, Integer.class);
}
@Override
protected void write() {
this.writeLong(this.id);
this.writeString(this.name);
this.writeInt(this.age);
this.writeList(skills);
this.writeMap(this.scopes);
}
@Override
public String toString() {
return "Id:" + this.id + " name:" + this.name + " age:" + this.age + " skills:" + this.skills;
}
}
package com.john.netty.learn.ch08;
import org.jboss.netty.buffer.ChannelBuffer;
import com.john.netty.learn.ch08.core.AbstractSerializer;
import com.john.netty.learn.ch08.core.Serializer;
public class Skill extends AbstractSerializer implements Serializer {
private int type;
private String desc;
public Skill() {
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
protected void read() {
this.type = this.readIntValue();
this.desc = this.readString();
}
@Override
protected void write() {
this.writeInt(this.type);
this.writeString(this.desc);
}
@Override
public String toString() {
return "Type:" + this.type +" Desc:" + this.desc;
}
}
所有源码下载 :https://download.youkuaiyun.com/download/netcobol/10308871