首先,我们知道序列化就是将对象变成字节数组,以便传输,而反序列化就是将字节数组变为原来的对象,这里我们借助Netty中的channelBuffer 来实现 ,其实channelBuffer可以理解为能动态扩容的Bytebuffe,能够自动扩容,这就好比数组与arrayList之间的关系,感兴趣的可以参照利用数组实现ArrayList的方式来实现自己的动态Bytebuffer,在这里不是重点,就不实现了
首先让我们来看一个简单的例子序列化例子
package com.lin.Serial;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import java.util.Arrays;
/**
* @author zoujianglin
* @date 2018/7/29 17:53
*/
public class Test1 {
public static void main(String[] args){
int id =5;
int age = 21;
ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer() ;
channelBuffer.writeInt(id);
channelBuffer.writeInt(age);
int index =channelBuffer.writerIndex();//写了多少字节 类似于bytebuffer中的position
byte[] bytes= new byte[index];
channelBuffer.readBytes(bytes); //将其中的字节读入到bytes中
System.out.println(Arrays.toString(bytes));
// ================================================
ChannelBuffer channelBuffer1 = ChannelBuffers.copiedBuffer(bytes); //创建一个含有bytes内容的ChannelBuffer
int id1= channelBuffer1.readInt();
int age1= channelBuffer1.readInt();
System.out.println("id:"+ id1+" "+"age1:"+age1);
}
}
上面就是我们自定义序列化的基本原理 ,总结起来就是将属性按照一定的顺序读入,在按照一定的顺序读出 看明白的上面的代码 接下来的话看起来就比较轻松了 首先我们定义一个buffer工厂用来获取channelbuffer
package com.lin.Serial;
import java.nio.ByteOrder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
/**
* @author zoujianglin
* @date 2018/7/29 18:07
*/
public class BufferFactory {
public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
/**
* 获取一个buffer
*
* @return
*/
public static ChannelBuffer getBuffer() {
ChannelBuffer dynamicBuffer = ChannelBuffers.dynamicBuffer();
return dynamicBuffer;
}
/**
* 将数据写入buffer
* @param bytes
* @return
*/
public static ChannelBuffer getBuffer(byte[] bytes) {
ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer(bytes);
return copiedBuffer;
}
}
接下啦就是要实现我们自己的序列化框架了,其中比较麻烦的是对象的集合和map等属性,对象属性,其代码逻辑有点长但都比较简单 ,耐心看的话还是比较容易看懂的
package com.lin.Serial;
import org.jboss.netty.buffer.ChannelBuffer;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;
/**
* @author zoujianglin
* @date 2018/7/29 18:23
*/
public abstract class Serializer {
public static final Charset CHARSET = Charset.forName("UTF-8");
protected ChannelBuffer writeBuffer;
protected ChannelBuffer readBuffer;
/**
* 反序列化具体实现
*/
protected abstract void read();
/**
* 序列化具体实现
*/
protected abstract void write();
/**
* 从byte数组获取数据
*
* @param bytes 读取的数组
*/
public Serializer readFromBytes(byte[] bytes) {
readBuffer = BufferFactory.getBuffer(bytes);
read();
readBuffer.clear();
return this;
}
/**
* 从buff获取数据
*
* @param readBuffer
*/
public void readFromBuffer(ChannelBuffer readBuffer) {
this.readBuffer = readBuffer;
read();
}
/**
* 写入本地buff
*
* @return
*/
public ChannelBuffer writeToLocalBuff() {
writeBuffer = BufferFactory.getBuffer();
write();
return writeBuffer;
}
/**
* 写入目标buff
*
* @param buffer
* @return
*/
public ChannelBuffer writeToTargetBuff(ChannelBuffer buffer) {
writeBuffer = buffer;
write(); //调用对象自身的序列化方法 需要自己覆盖
return writeBuffer;
}
/**
* 返回buffer数组
*
* @return
*/
public byte[] getBytes() {
writeToLocalBuff();
byte[] bytes = null;
if (writeBuffer.writerIndex() == 0) {
bytes = new byte[0];
} else {
bytes = new byte[writeBuffer.writerIndex()];
writeBuffer.readBytes(bytes);
}
writeBuffer.clear();
return bytes;
}
public byte readByte() {
return readBuffer.readByte();
}
public short readShort() {
return readBuffer.readShort();
}
public int readInt() {
return readBuffer.readInt();
}
public long readLong() {
return readBuffer.readLong();
}
public float readFloat() {
return readBuffer.readFloat();
}
public double readDouble() {
return readBuffer.readDouble();
}
public String readString() {
int size = readBuffer.readShort();
if (size <= 0) {
return "";
}
byte[] bytes = new byte[size];
readBuffer.readBytes(bytes);
try {
return new String(bytes, "UTF-8");
} catch (Exception e) {
throw new RuntimeException("字符编码错误");
}
}
public <T> List<T> readList(Class<T> clz) {
List<T> list = new ArrayList<T>();
int size = readBuffer.readShort();
for (int i = 0; i < size; i++) {
list.add(read(clz));
}
return list;
}
public <K, V> Map<K, V> readMap(Class<K> keyClz, Class<V> valueClz) {
Map<K, V> map = new HashMap<K, V>();
int size = readBuffer.readShort();
for (int i = 0; i < size; i++) {
K key = read(keyClz);
V value = read(valueClz);
map.put(key, value);
}
return map;
}
@SuppressWarnings("unchecked")
public <I> I read(Class<I> clz) {
Object t = null;
if (clz == int.class || clz == Integer.class) {
t = this.readInt();
} else if (clz == byte.class || clz == Byte.class) {
t = this.readByte();
} else if (clz == short.class || clz == Short.class) {
t = this.readShort();
} else if (clz == long.class || clz == Long.class) {
t = this.readLong();
} else if (clz == float.class || clz == Float.class) {
t = readFloat();
} else if (clz == double.class || clz == Double.class) {
t = readDouble();
} else if (clz == String.class) {
t = readString();
} else if (Serializer.class.isAssignableFrom(clz)) {
try {
byte hasObject = this.readBuffer.readByte();
if (hasObject == 1) {
Serializer temp = (Serializer) clz.newInstance();
temp.readFromBuffer(this.readBuffer);
t = temp;
} else {
t = null;
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
throw new RuntimeException(String.format("不支持类型:[%s]", clz));
}
return (I) t;
}
public Serializer writeByte(Byte value) {
writeBuffer.writeByte(value);
return this;
}
public Serializer writeShort(Short value) {
writeBuffer.writeShort(value);
return this;
}
public Serializer writeInt(Integer value) {
writeBuffer.writeInt(value);
return this;
}
public Serializer writeLong(Long value) {
writeBuffer.writeLong(value);
return this;
}
public Serializer writeFloat(Float value) {
writeBuffer.writeFloat(value);
return this;
}
public Serializer writeDouble(Double value) {
writeBuffer.writeDouble(value);
return this;
}
public <T> Serializer writeList(List<T> list) {
if (isEmpty(list)) {
writeBuffer.writeShort((short) 0);
return this;
}
writeBuffer.writeShort((short) list.size()); //先写入list的size()
for (T item : list) {
writeObject(item);
}
return this;
}
public <K, V> Serializer writeMap(Map<K, V> map) {
if (isEmpty(map)) {
writeBuffer.writeShort((short) 0);
return this;
}
writeBuffer.writeShort((short) map.size()); //先写入map的size()
for (Entry<K, V> entry : map.entrySet()) {
writeObject(entry.getKey());
writeObject(entry.getValue());
}
return this;
}
public Serializer writeString(String value) {
if (value == null || value.isEmpty()) {
writeShort((short) 0);
return this;
}
byte data[] = value.getBytes(CHARSET);
short len = (short) data.length;
writeBuffer.writeShort(len);
writeBuffer.writeBytes(data);
return this;
}
public Serializer writeObject(Object object) {
if (object == null) {
writeByte((byte) 0);
} else {
if (object instanceof Integer) {
writeInt((Integer) object);
return this;
}
if (object instanceof Long) {
writeLong((Long) object);
return this;
}
if (object instanceof Short) {
writeShort((Short) object);
return this;
}
if (object instanceof Byte) {
writeByte((Byte) object);
return this;
}
if (object instanceof String) {
String value = (String) object;
writeString(value);
return this;
}
if (object instanceof Serializer) {
writeByte((byte) 1);
Serializer value = (Serializer) object;
value.writeToTargetBuff(writeBuffer);
return this;
}
throw new RuntimeException("不可序列化的类型:" + object.getClass());
}
return this;
}
private <T> boolean isEmpty(Collection<T> c) {
return c == null || c.size() == 0;
}
public <K, V> boolean isEmpty(Map<K, V> c) {
return c == null || c.size() == 0;
}
}
到这里就完成了 接下来我们就来测试一下
package com.lin.Serial;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import java.util.Arrays;
/**
* @author zoujianglin
* @date 2018/7/29 17:53
*/
public class Test1 extends Serializer {
private static int age;
private static int id;
public Test1(int age, int id) {
this.id = id;
this.age = age;
}
public Test1() {
}
public static void main(String[] args) {
Test1 test1 = new Test1(12, 23);
byte[] bytes= test1.getBytes(); //序列化 字节数组
Test1 test2 = new Test1();
test2.readFromBytes(bytes); 反序列化
System.out.println(test2.id+" "+test2.age);
}
@Override
protected void read() {
//注意读入和写入的顺序要一致
this.age = this.readInt();
this.id = this.readInt();
}
@Override
protected void write() {
int t= this.age;
this.writeInt(this.age);
this.writeInt(this.id);
}
}
发现反序列化后对象属性一致,到此就完成了 !!!!
953

被折叠的 条评论
为什么被折叠?



