Netty进阶之路-MessagePack编解码

8 篇文章 1 订阅

前言

之前的Netty利用json和LineBasedFrameDecoder和StringDecoder来实现数据传输和解决粘包/半包问题。后来发现Netty支持更高效的编解码例如MessagePack。本篇主要来讲讲MessagePack的使用。

MessagePack优点

MessagePack是一个高效的二进制序列化框架

  1. 和json一样支持跨语言
  2. 序列化之后的码流更小
  3. 编解码性能高效

Netty客户端–MessagePack编解码

Netty提供了丰富的编解码器抽象基类,我们可以很容易的实现这些基类来自定义编解码器。

Netty客户端–MessagePack编码

这里将需要编码的对象加上@Message注解
我之前 result属性用的是Object 因为返回类型可能是List或者Map或者String等但是在MessagePack中不能使用Object 类型 所有我改成了String。

@Message
public class RPCRequest {

	private String requestID;
	private String className;
	private String methodName;
	private String[] parameters;
	private String result;
	
	public String getRequestID() {
		return requestID;
	}
	public void setRequestID(String requestID) {
		this.requestID = requestID;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	public String[] getParameters() {
		return parameters;
	}
	public void setParameters(String[] parameters) {
		this.parameters = parameters;
	}
	public String getResult() {
		return result;
	}
	public void setResult(String result) {
		this.result = result;
	}
	
	
}

利用Netty基类来自定义编码器

public class ClientMsgPackEncode extends MessageToByteEncoder<Object>{

	@Override
	protected void encode(ChannelHandlerContext arg0, Object msg, ByteBuf out)
			throws Exception {
			RPCRequest request = (RPCRequest) msg;
			MessagePack msgPack = new MessagePack();
			//msgPack.register(RPCRequest.class);
			byte[] raw = null;
			raw = msgPack.write(request);
			out.writeBytes(raw);	
	}
}

Netty客户端–MessagePack解码

@Message
public class RPCResponse {
    private String requestID;
    private String result;

    public String getRequestID() {
        return requestID;
    }

    public void setRequestID(String requestID) {
        this.requestID = requestID;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

利用Netty基类来自定义解码器

public class ClientMsgPackDecode extends MessageToMessageDecoder<ByteBuf>{

	@Override
	protected void decode(ChannelHandlerContext arg0, ByteBuf msg,
			List<Object> out) throws Exception {
		// TODO Auto-generated method stub
		final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgPack = new MessagePack();
        out.add(msgPack.read(array,RPCResponse.class));
	}

}

Netty客户端–编解码使用

在链路里添加

ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));
ch.pipeline().addLast(new LengthFieldPrepender(2));
ch.pipeline().addLast(new ClientMsgPackEncode());//编码
ch.pipeline().addLast(new ClientMsgPackDecode());//解码
ch.pipeline().addLast(new RPCRequestHandler());//添加相应回调处理和编解码器

之后的发送消息和读取消息可以直接使用对象

Netty服务端–MessagePack编解码

说明一下 客户端服务端用了2套的原因是编解码的时候对象不是同一个
例如客户端编码是RPCRequest对象 服务端编码RPCResponse 对象。

Netty服务端–MessagePack解码

public class ServerMsgPackDecode extends MessageToMessageDecoder<ByteBuf>{

	@Override
	protected void decode(ChannelHandlerContext arg0, ByteBuf msg,
			List<Object> out) throws Exception {
		// TODO Auto-generated method stub
		final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgPack = new MessagePack();
        out.add(msgPack.read(array,RPCRequest.class));
	}

}

Netty服务端–MessagePack编码

public class ServerMsgPackEncode extends MessageToByteEncoder<Object>{

	@Override
	protected void encode(ChannelHandlerContext arg0, Object msg, ByteBuf out)
			throws Exception {
		RPCResponse RPCResponse = (RPCResponse) msg;
		MessagePack msgPack = new MessagePack();
		//msgPack.register(RPCResponse.class);
        byte[] raw = null;
        raw = msgPack.write(RPCResponse);
        out.writeBytes(raw);	
	}

}

Netty服务端–编解码使用

同样在链路里添加

socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));//编码
socketChannel.pipeline().addLast(new LengthFieldPrepender(2));
socketChannel.pipeline().addLast(new ServerMsgPackEncode());//编码
socketChannel.pipeline().addLast(new ServerMsgPackDecode());//解码
socketChannel.pipeline().addLast(new RPCResponseHandler());//处理类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值