Netty进阶之路-MessagePack编解码

导读:本篇文章讲解 Netty进阶之路-MessagePack编解码,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前言

之前的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());//处理类

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15327.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!