Netty自定义序列化协议
自定义序列化协议
序列化的目的就是想对象转化成字节数组byteArray
阶段一
使用流的形式
public class Test{
public static void main(String[] args) throws IOException {
int id = 100;
int age = 22;
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
arrayOutputStream.write(int2bytes(id));//序列化
arrayOutputStream.write(int2bytes(age));
byte[] byteArray = arrayOutputStream.toByteArray();
//==================通过socket传输字节序列=================================
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(byteArray);
byte[] idBytes = new byte[4];//读取4个字节
arrayInputStream.read(idBytes);
System.out.println("id:" + bytes2int(idBytes));//反序列化
byte[] ageBytes = new byte[4];
arrayInputStream.read(ageBytes);
System.out.println("age:" + bytes2int(ageBytes));
}
/*
* int 类型占4个字节 采用大端字节序列(高位在前面)
*/
//序列化
public static byte[] int2byte(int i)
{
byte[]bytes =new byte[4];
bytes[0]=(byte)(i >> 3*8);
bytes[1]=(byte)(i >> 2*8);
bytes[2]=(byte)(i >> 1*8);
bytes[3]=(byte)(i >> 0*8);
return bytes;
}
//反序列化
pulic static int byte2int(byte[]bytes)
{
return (bytes[0] << 3*8) |
(bytes[1] << 2*8) |
(bytes[2] << 1*8) |
(bytes[3] << 0*8);}
}
阶段二
使用byteBuff 完成序列化部分
- 可以对多种类型进行序列化、反序列化操作
- byteBuff要声明大小,且不能自动拓展
****OutputStream、***InputStream具有自动扩容的方法
public static void main(String[] args) throws IOException {
int id = 100;
nt age = 22;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putInt(id);
buffer.putInt(age);
byte[] byteArray = buffer.array();
//==================通过socket传输字节序列=================================
ByteBuffer buffer2 = ByteBuffer.wrap(array);
System.out.println("id:"+buffer2.getInt());
System.out.println("age:"+buffer2.getInt());
阶段三
使用Netty ChannelBuffer
- 可以自动扩容,并且可以对多种整型数据类型进行序列化、反序列化操作
不能对操作String
public static void main(String[] args) {
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
buffer.writeInt(101);
buffer.writeDouble(80.1);
byte[] bytes = new byte[buffer.writerIndex()];
buffer.readBytes(bytes);
System.out.println(Arrays.toString(bytes));
"abc".getBytes();
//================================================
ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
System.out.println(wrappedBuffer.readInt());
System.out.println(wrappedBuffer.readDouble());
}
阶段四
Netty ChannelBuffer对进行集成处理
- 在阶段三的基础上支持String、List等数据类型
- 实现对类对象的序列化
- 继承Serializer抽象类(借助Netty自定义的序列化规则)
- 重写read()、write()时属性顺序要一致
如果属性是对象的话(如,Resource),同样也要继承Serializer抽象类
public class Player extends Serializer{
private long playerId;
private int age;
private List<Integer> skills = new ArrayList<>();
private Resource resource = new Resource();
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
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 List<Integer> getSkills() {
return skills;
}
public void setSkills(List<Integer> skills) {
this.skills = skills;
}
@Override
protected void read() {
this.playerId = readLong();
this.age = readInt();
this.skills = readList(Integer.class);
this.resource = read(Resource.class);
}
@Override
protected void write() {
writeLong(playerId);
writeInt(age);
writeList(skills);
writeObject(resource);
}
}
使用案例
- Player、Resource对象继承了Serializer抽象类
- 序列化:player.getBytes()
反序列:player2.readFromBytes(bytes)
public static void main(String[] args) {
Player player = new Player();
player.setPlayerId(10001);
player.setAge(22);
player.getSkills().add(101);
player.getResource().setGold(99999);
byte[] bytes = player.getBytes();//内部调用write()进行序列化
System.out.println(Arrays.toString(bytes));
//==============================================
Player player2 = new Player();
player2.readFromBytes(bytes);//内部调用read()进行反序列化
System.out.println(player2.getPlayerId() + " "+player2.getAge() + " "+ Arrays.toString(player2.getSkills().toArray())+" " +player2.getResource().getGold());
}
阶段5
Protocol Buff 对阶段四的进一步优化
- 在客户端和服务器都配置序列化配置文件
ProtocolBuff内部通过位运算,可以避免Java本身数据类型新建造成空间的浪费,从而更加高效的完成序列化
//序列化
public static byte[] toBytes() throws IOException{
//获取一个user的构造器
Builder builder =PlayerModule.user.newBuidler();
//设置数据
builder.setId(10).setAge(18).setName(“luo”).addSkills(1001);
//构造对象
User user =builder.build();
//序列化成字节数组
byte[] byteArray= user.toByteArray();
return byteArray;
}
//反序列化
public static void toPlayer(byte[] bs) throws Exception{
ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bs));
User player = (User)inputStream.readObject();
//打印
System.out.println("Id:" + player.getPlayerId());
System.out.println("age:" + player.getAge());
System.out.println("name:" + player.getName());
System.out.println("skills:" + (Arrays.toString(player.getSkills().toArray())));
}
还没有评论,来说两句吧...