博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用netty 3的channelbuffer来重写序列化类
阅读量:7201 次
发布时间:2019-06-29

本文共 12183 字,大约阅读时间需要 40 分钟。

hot3.png

我们都知道用java来序列化一个对象,需要用到ObjectOutputSteam来把对象写进一个字节流ByteOutputStream,然后把字节流转成字节数组。用ObjectInputSteam来反序列化,获取一个字节流,再读出对象。类似代码如下。

序列化类代码

package com.netty.java;import java.io.Serializable;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2018-05-22. */public class Player implements Serializable{    private static final long serialVersionUID = -8914730421956537399L;    private long playerId;    private int age;    private String name;    private List
skills = new ArrayList<>(); public Player(long playerId,int age,String name) { this.playerId = playerId; this.age = age; this.name = name; } public long getPlayerId() { return playerId; } public void setPlayerId(long playerId) { this.playerId = playerId; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List
getSkills() { return skills; } public void setSkills(List
skills) { this.skills = skills; }}

序列化和反序列化代码如下

package com.netty.java;import java.io.*;import java.util.Arrays;/** * Created by Administrator on 2018-05-22. */public class Java2Bytes {    public static void main(String[] args) throws IOException, ClassNotFoundException {        byte[] bytes = toBytes();        toPlayer(bytes);    }    public static byte[] toBytes() throws IOException {        Player player = new Player(101,20,"天王乔嘉");        player.getSkills().add(1001);        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);        objectOutputStream.writeObject(player);        byte[] byteArray = byteArrayOutputStream.toByteArray();        System.out.println(Arrays.toString(byteArray));        return byteArray;    }    public static void toPlayer(byte[] bs) throws IOException, ClassNotFoundException {        ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bs));        Player player = (Player) inputStream.readObject();        System.out.println("PlayerId:" + player.getPlayerId() + " name:" + player.getName() + " age:" + player.getAge() + " skills:" + Arrays.toString(player.getSkills().toArray()));    }}

运行后的结果为

[-84, -19, 0, 5, 115, 114, 0, 21, 99, 111, 109, 46, 110, 101, 116, 116, 121, 46, 106, 97, 118, 97, 46, 80, 108, 97, 121, 101, 114, -124, 72, -125, -23, -38, -23, -109, -55, 2, 0, 4, 73, 0, 3, 97, 103, 101, 74, 0, 8, 112, 108, 97, 121, 101, 114, 73, 100, 76, 0, 4, 110, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 6, 115, 107, 105, 108, 108, 115, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 120, 112, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 101, 116, 0, 12, -27, -92, -87, -25, -114, -117, -28, -71, -108, -27, -104, -119, 115, 114, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 65, 114, 114, 97, 121, 76, 105, 115, 116, 120, -127, -46, 29, -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105, 122, 101, 120, 112, 0, 0, 0, 1, 119, 4, 0, 0, 0, 1, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 3, -23, 120]

PlayerId:101 name:天王乔嘉 age:20 skills:[1001]

现在用netty 3 channelbuffer来重写这个过程,我们需要一个序列化的抽象类以及buffer工厂

package com.netty.serializer;import org.jboss.netty.buffer.ChannelBuffer;import java.nio.charset.Charset;import java.util.*;/** * Created by Administrator on 2018-05-21. */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();    public Serializer readFromBytes(byte[] bytes) {        readBuffer = BufferFactory.getBuffer(bytes);        read();        readBuffer.clear();        return this;    }    public void readFromBuffer(ChannelBuffer readBuffer) {        this.readBuffer = readBuffer;        read();    }    public ChannelBuffer writeToLocalBuff() {        writeBuffer = BufferFactory.getBuffer();        write();        return writeBuffer;    }    public ChannelBuffer writeToTargetBuff(ChannelBuffer buffer) {        writeBuffer = buffer;        write();        return writeBuffer;    }    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();    }    @SuppressWarnings("Since15")    public String readString() {        int size = readBuffer.readShort();        if (size <= 0) {            return "";        }        byte[] bytes = new byte[size];        readBuffer.readBytes(bytes);        return new String(bytes, CHARSET);    }    public 
List
readList(Class
clz) { List
list = new ArrayList
(); int size = readBuffer.readShort(); for (int i = 0;i < size;i++) { list.add(read(clz)); } return list; } public
Map
readMap(Class
keyClz,Class
valueClz) { Map
map = new HashMap
(); 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; } public
I read(Class 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 = this.readFloat(); }else if (clz == double.class || clz == Double.class) { t = this.readDouble(); }else if (clz == String.class) { t = this.readString(); }else if (Serializer.class.isAssignableFrom(clz)) { try { byte hasObject = this.readBuffer.readByte(); if (hasObject == 1) { Serializer team = (Serializer)clz.newInstance(); team.readFromBuffer(this.readBuffer); t = team; }else { t = null; } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException 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
Serializer writeList(List
list) { if (isEmpty(list)) { writeBuffer.writeShort((short)0); return this; } writeBuffer.writeShort((short)list.size()); for (T item:list) { writeObject(item); } return this; } public
Serializer writeMap(Map
map) { if (isEmpty(map)) { writeBuffer.writeShort((short)0); return this; } writeBuffer.writeShort((short)map.size()); for (Map.Entry
entry:map.entrySet()) { writeObject(entry.getKey()); writeObject(entry.getValue()); } return this; } @SuppressWarnings("Since15") 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
boolean isEmpty(Collection
c) { return c == null || c.size() == 0; } private
boolean isEmpty(Map
c) { return c == null || c.size() == 0; }}
package com.netty.serializer;import org.jboss.netty.buffer.ChannelBuffer;import org.jboss.netty.buffer.ChannelBuffers;import java.nio.ByteOrder;/** * Created by Administrator on 2018-05-21. */public class BufferFactory {    public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;    public static ChannelBuffer getBuffer() {        ChannelBuffer dynamicBuffer = ChannelBuffers.dynamicBuffer();        return dynamicBuffer;    }    public static ChannelBuffer getBuffer(byte[] bytes) {        ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer(bytes);        return copiedBuffer;    }}

我们要序列化的实体类要继承该抽象类,并实现各自的抽象方法。

package com.netty.serializer;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2018-05-22. */public class Player extends Serializer {    private int id;    private String name;    private int age;    private List
skills = new ArrayList<>(); public List
getSkills() { return skills; } public void setSkills(List
skills) { this.skills = skills; } public int getId() { return id; } public void setId(int 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; } @Override protected void read() { this.id = readInt(); this.name = readString(); this.age = readInt(); this.skills = readList(Integer.class); } @Override protected void write() { writeInt(id); writeString(name); writeInt(age); writeList(skills); }}

序列化和反序列化主类

package com.netty.serializer;import java.util.Arrays;/** * Created by Administrator on 2018-05-22. */public class Test {    public static void main(String[] args) {        Player player = new Player();        player.setId(101);        player.setName("天王乔嘉");        player.setAge(45);        player.getSkills().add(1001);        byte[] bytes = player.getBytes();        System.out.println(Arrays.toString(bytes));        Player player1 = new Player();        player1.readFromBytes(bytes);        System.out.println(player1.getId() + " " + player1.getName() + " " + player1.getAge() +" " + Arrays.toString(player1.getSkills().toArray()));    }}

运行的结果为

[0, 0, 0, 101, 0, 12, -27, -92, -87, -25, -114, -117, -28, -71, -108, -27, -104, -119, 0, 0, 0, 45, 0, 1, 0, 0, 3, -23]

101 天王乔嘉 45 [1001]

对比结果发现序列化的长度,后者比前者小很多。

当然最小的序列化还是google的protoBuffer,这个是要自己去定义protobuffer的*.proto文件的。

转载于:https://my.oschina.net/u/3768341/blog/1817034

你可能感兴趣的文章