Netty实战练习——自定义Encoder和Decoder

目录

实现encoder和decoder的方法

一、利用netty

1、实现messageToByte,使用java原生的序列化方式

2、利用netty支持的现有序列化框架

3、自定义序列化协议

二、在handler的read和write方法中直接实现

tcp拆包粘包见下篇


需求:

1、客户端向服务端发送自定义类InputParam:

public class InputParam {
    private int num1;
    private int num2;
}

2、服务端接受到InputParam,发送对应的OutputParam:

public class OutputParam {
    private String str1;
    private String str2;
}

实现encoder和decoder的方法

实现encoder和decoder本质上就是序列化和反序列化。

一、利用netty

1、实现messageToByte,使用java原生的序列化方式

java序列化与反序列化的介绍参考:https://blog.csdn.net/weixin_43599368/article/details/84496207

客户端解码器:(byte -> outputParam,相当于outputParam的反序列化,用ObjectInputStream)

public class ClientMessageDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
        ObjectInputStream inputStream = new ObjectInputStream(new ByteBufInputStream(in));
        OutputParam outputParam = (OutputParam)inputStream.readObject();
        out.add(outputParam);
    }
} 
  

客户端编码器:(inputParam -> byte,相当于inputParam的序列化,用ObjectOutputStream)

public class ClientMessageEncoder extends MessageToByteEncoder {

    @Override
    protected void encode(ChannelHandlerContext ctx, InputParam msg, ByteBuf out) throws Exception {
        ObjectOutputStream o = new ObjectOutputStream(new ByteBufOutputStream(out));
        o.writeObject(msg);
    }
}

服务端解码器:(byte -> inputParam,相当于inputParam的反序列化,用ObjectInputStream)

public class ServerMessageDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
        ObjectInputStream inputStream = new ObjectInputStream(new ByteBufInputStream(in));
        InputParam inputParam = (InputParam)inputStream.readObject();
        out.add(inputParam);
    }
} 
  

服务端编码器:(outputParam -> byte,相当于outParam的序列化,用ObjectOutputStream)

public class ServerMessageEncoder extends MessageToByteEncoder {
    @Override
    protected void encode(ChannelHandlerContext ctx, OutputParam msg, ByteBuf out) throws Exception {
        ObjectOutputStream o = new ObjectOutputStream(new ByteBufOutputStream(out));
        o.writeObject(msg);
    }
}

2、利用netty支持的现有序列化框架

此处要用到的是MessagePack

关于MessagePack

It’s like JSON.
but fast and small.

MessagePack是一种高效的二进制序列化格式。它允许您像JSON一样在多个语言之间交换数据。但是,它更快并且更小。小整数被编码为一个字节,和典型的短字符串只需要除了字符串本身的一个额外字节。

客户端解码器:(byte -> outputParam)

public class ClientMessageDecoder extends MessageToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception {
        //获取要解码的byte数组
        final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        //调用MessagePack 的read方法将其反序列化为Object对象
        msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgpack = new MessagePack();
        OutputParam outputParam = msgpack.read(array, OutputParam.class);
        out.add(outputParam);
    }

}
 
  

客户端编码器:(inputParam -> byte)

public class ClientMessageEncoder extends MessageToByteEncoder {

    @Override
    protected void encode(ChannelHandlerContext ctx, InputParam msg, ByteBuf out) throws Exception {
        MessagePack msgpack = new MessagePack();
        out.writeBytes(msgpack.write(msg));
    }
}

服务端解码器:(byte -> inputParam)

public class ServerMessageDecoder extends MessageToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception {
        //获取要解码的byte数组
        final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        //调用MessagePack 的read方法将其反序列化为Object对象
        msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgpack = new MessagePack();
        InputParam inputParam = msgpack.read(array, InputParam.class);
        out.add(inputParam);
    }


}
 
  

服务端编码器:(outputParam -> byte)

public class ServerMessageEncoder extends MessageToByteEncoder {
    @Override
    protected void encode(ChannelHandlerContext ctx, OutputParam msg, ByteBuf out) throws Exception {
        MessagePack msgpack = new MessagePack();
        out.writeBytes(msgpack.write(msg));
    }
}

说明:

<1>使用MessagePack,必须要在需要序列化的model上添加@Message注解

@Message
public class InputParam {
    private int num1;
    private int num2;

    public int getNum1() {
        return num1;
    }

    public void setNum1(int num1) {
        this.num1 = num1;
    }

    public int getNum2() {
        return num2;
    }

    public void setNum2(int num2) {
        this.num2 = num2;
    }

    @Override
    public String toString() {
        return "InputParam{" +
                "num1=" + num1 +
                ", num2=" + num2 +
                '}';
    }

}
@Message
public class OutputParam {
    private String str1;
    private String str2;

    public String getStr1() {
        return str1;
    }

    public void setStr1(String str1) {
        this.str1 = str1;
    }

    public String getStr2() {
        return str2;
    }

    public void setStr2(String str2) {
        this.str2 = str2;
    }

    @Override
    public String toString() {
        return "OutputParam{" +
                "str1='" + str1 + '\'' +
                ", str2='" + str2 + '\'' +
                '}';
    }

}

<2>netty内置的Encoder或者Decoder类的泛型都是源类型。

eg:解码器从byte到model,泛型是bytebuf

public class ClientMessageDecoder extends MessageToMessageDecoder 

包括第一种的byteToMessageDecoder

<3>详细介绍下MessageToMessageDecoder/MessageToMessageEncoder,可以实现pojo到pojo的编解码

如Integer -> String

public class IntegerToStringDecoder extends
        MessageToMessageDecoder { //1

    @Override
    public void decode(ChannelHandlerContext ctx, Integer msg, List out)
            throws Exception {
        out.add(String.valueOf(msg)); //2
    }
} 
  

3、自定义序列化协议

参考https://blog.csdn.net/qq_32459653/article/details/81274704

二、在handler的read和write方法中直接实现

tcp拆包粘包见下篇

https://blog.csdn.net/weixin_43599368/article/details/84504440

你可能感兴趣的:(netty)