首先,我们知道序列化就是将对象变成字节数组,以便传输,而反序列化就是将字节数组变为原来的对象,这里我们借助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); } }
发现反序列化后对象属性一致,到此就完成了 !!!!