Netty自定义序列化协议

谁践踏了优雅 2021-12-14 12:03 475阅读 0赞

自定义序列化协议

序列化的目的就是想对象转化成字节数组byteArray

阶段一
使用流的形式

  1. public class Test{
  2. public static void main(String[] args) throws IOException {
  3. int id = 100;
  4. int age = 22;
  5. ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
  6. arrayOutputStream.write(int2bytes(id));//序列化
  7. arrayOutputStream.write(int2bytes(age));
  8. byte[] byteArray = arrayOutputStream.toByteArray();
  9. //==================通过socket传输字节序列=================================
  10. ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(byteArray);
  11. byte[] idBytes = new byte[4];//读取4个字节
  12. arrayInputStream.read(idBytes);
  13. System.out.println("id:" + bytes2int(idBytes));//反序列化
  14. byte[] ageBytes = new byte[4];
  15. arrayInputStream.read(ageBytes);
  16. System.out.println("age:" + bytes2int(ageBytes));
  17. }
  18. /*
  19. * int 类型占4个字节 采用大端字节序列(高位在前面)
  20. */
  21. //序列化
  22. public static byte[] int2byte(int i)
  23. {
  24. byte[]bytes =new byte[4];
  25. bytes[0]=(byte)(i >> 3*8);
  26. bytes[1]=(byte)(i >> 2*8);
  27. bytes[2]=(byte)(i >> 1*8);
  28. bytes[3]=(byte)(i >> 0*8);
  29. return bytes;
  30. }
  31. //反序列化
  32. pulic static int byte2int(byte[]bytes)
  33. {
  34. return (bytes[0] << 3*8) |
  35. (bytes[1] << 2*8) |
  36. (bytes[2] << 1*8) |
  37. (bytes[3] << 0*8);}
  38. }

阶段二
使用byteBuff 完成序列化部分

  • 可以对多种类型进行序列化、反序列化操作
  • byteBuff要声明大小,且不能自动拓展
  • ****OutputStream、***InputStream具有自动扩容的方法

    public static void main(String[] args) throws IOException {

    1. int id = 100;
    2. nt age = 22;
    3. ByteBuffer buffer = ByteBuffer.allocate(8);
    4. buffer.putInt(id);
    5. buffer.putInt(age);
    6. byte[] byteArray = buffer.array();
    7. //==================通过socket传输字节序列=================================
    8. ByteBuffer buffer2 = ByteBuffer.wrap(array);
    9. System.out.println("id:"+buffer2.getInt());
    10. System.out.println("age:"+buffer2.getInt());

阶段三
使用Netty ChannelBuffer

  • 可以自动扩容,并且可以对多种整型数据类型进行序列化、反序列化操作
  • 不能对操作String

    public static void main(String[] args) {

    1. ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
    2. buffer.writeInt(101);
    3. buffer.writeDouble(80.1);
    4. byte[] bytes = new byte[buffer.writerIndex()];
    5. buffer.readBytes(bytes);
    6. System.out.println(Arrays.toString(bytes));
    7. "abc".getBytes();
    8. //================================================
    9. ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
    10. System.out.println(wrappedBuffer.readInt());
    11. System.out.println(wrappedBuffer.readDouble());
    12. }

阶段四
Netty ChannelBuffer对进行集成处理

  • 在阶段三的基础上支持String、List等数据类型
  • 实现对类对象的序列化
  • 继承Serializer抽象类(借助Netty自定义的序列化规则)
  • 重写read()、write()时属性顺序要一致
  • 如果属性是对象的话(如,Resource),同样也要继承Serializer抽象类

    public class Player extends Serializer{

    1. private long playerId;
    2. private int age;
    3. private List<Integer> skills = new ArrayList<>();
    4. private Resource resource = new Resource();
    5. public Resource getResource() {
    6. return resource;
    7. }
    8. public void setResource(Resource resource) {
    9. this.resource = resource;
    10. }
    11. public long getPlayerId() {
    12. return playerId;
    13. }
    14. public void setPlayerId(long playerId) {
    15. this.playerId = playerId;
    16. }
    17. public int getAge() {
    18. return age;
    19. }
    20. public void setAge(int age) {
    21. this.age = age;
    22. }
    23. public List<Integer> getSkills() {
    24. return skills;
    25. }
    26. public void setSkills(List<Integer> skills) {
    27. this.skills = skills;
    28. }
    29. @Override
    30. protected void read() {
    31. this.playerId = readLong();
    32. this.age = readInt();
    33. this.skills = readList(Integer.class);
    34. this.resource = read(Resource.class);
    35. }
    36. @Override
    37. protected void write() {
    38. writeLong(playerId);
    39. writeInt(age);
    40. writeList(skills);
    41. writeObject(resource);
    42. }

    }

使用案例

  • Player、Resource对象继承了Serializer抽象类
  • 序列化:player.getBytes()
  • 反序列:player2.readFromBytes(bytes)

    public static void main(String[] args) {

    1. Player player = new Player();
    2. player.setPlayerId(10001);
    3. player.setAge(22);
    4. player.getSkills().add(101);
    5. player.getResource().setGold(99999);
    6. byte[] bytes = player.getBytes();//内部调用write()进行序列化
    7. System.out.println(Arrays.toString(bytes));
    8. //==============================================
    9. Player player2 = new Player();
    10. player2.readFromBytes(bytes);//内部调用read()进行反序列化
    11. System.out.println(player2.getPlayerId() + " "+player2.getAge() + " "+ Arrays.toString(player2.getSkills().toArray())+" " +player2.getResource().getGold());
    12. }
  • 阶段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;
    }

  1. //反序列化
  2. public static void toPlayer(byte[] bs) throws Exception{
  3. ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bs));
  4. User player = (User)inputStream.readObject();
  5. //打印
  6. System.out.println("Id:" + player.getPlayerId());
  7. System.out.println("age:" + player.getAge());
  8. System.out.println("name:" + player.getName());
  9. System.out.println("skills:" + (Arrays.toString(player.getSkills().toArray())));
  10. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,475人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Netty实现定义协议

    关于协议,使用最为广泛的是HTTP协议,但是在一些服务交互领域,其使用则相对较少,主要原因有三方面: HTTP协议会携带诸如header和cookie等信息,其本身对字

    相关 netty定义协议

    《netty权威指南》一书中关于自定义协议开发的源码中有一部分错误导致代码无法运行,加了一点改变可以完美运行了, package nettyAgreement.dec

    相关 Netty序列协议Protocol buff

    序列化协议 序列化和反序列化 把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。用途:文件的copy、网络数据的传输 Pro