Netty自定义编码解码器

上次通信的时候用的是自带的编解码器,今天自己实现一下自定义的。

1、自定义一下协议

复制代码
//协议类
@Data
public class Protocol<T> implements Serializable {

    private Long id = System.currentTimeMillis();

    private short msgType;// 假设1为请求 2为响应

    private T body;
    
}

//消息请求体
@Data
public class RequestMsg implements Serializable {

    private String msg;

    private String other;

}

//消息响应体
@Data
public class ResponseMsg implements Serializable {

    private String result;

    private String error;

}

2、定义编解码器import io.netty.buffer.ByteBuf;

复制代码
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

//编码器
public class EnCodeMsg extends MessageToByteEncoder<Protocol<Object>> {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Protocol<Object> msg, ByteBuf byteBuf) throws Exception {
        Serialization serialization = new JdkSerialization();
        byte[] body = serialization.serialize(msg.getBody());
        int length = body.length;
        Long id = msg.getId();
        short msgType = msg.getMsgType();
        byteBuf.writeLong(id);
        byteBuf.writeShort(msgType);
        byteBuf.writeInt(length);
        byteBuf.writeBytes(body);
    }
}


import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

//解码器
public class DeCodeMsg extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
        Serialization serialization = new JdkSerialization();
        long id = in.readLong();
        short msgType = in.readShort();
        int bodyLength = in.readInt();
        int i = in.readableBytes();
        if(bodyLength!=i){
            in.resetReaderIndex();
            return;
        }
        byte[] bytes = new byte[bodyLength];
        in.readBytes(bytes);
        if(msgType==(short)1){
            Protocol<RequestMsg> requestMsgProtocol = new Protocol<>();
            RequestMsg requestMsg = serialization.deserialize(bytes, RequestMsg.class);
            requestMsgProtocol.setBody(requestMsg);
            requestMsgProtocol.setId(id);
            requestMsgProtocol.setMsgType(msgType);
            list.add(requestMsgProtocol);
        }else if(msgType==(short)2){
            Protocol<ResponseMsg> responseMsgProtocol = new Protocol<>();
            ResponseMsg responseMsg = serialization.deserialize(bytes,ResponseMsg.class);
            responseMsgProtocol.setId(id);
            responseMsgProtocol.setMsgType(msgType);
            responseMsgProtocol.setBody(responseMsg);
            list.add(responseMsgProtocol);
        }else {
            return;
        }

    }
}

3、修改消息处理器

复制代码
public class NettyClientHandler extends SimpleChannelInboundHandler<Protocol<ResponseMsg>> {

    private static final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);

    private volatile Channel channel;

    private SocketAddress remotePeer;

    public Channel getChannel() {
        return channel;
    }

    public SocketAddress getRemotePeer() {
        return remotePeer;
    }

    /**
     * 注册
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        logger.info("channelRegistered--------------");
        super.channelRegistered(ctx);
        this.channel = ctx.channel();
    }

    /**
     * 激活
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        this.remotePeer = this.channel.remoteAddress();
        logger.info("channelActive--------------");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext,Protocol<ResponseMsg> o) throws Exception {
        logger.info("channelRead0--------------"+Thread.currentThread().getName());
        logger.info("消费者接收到的消息为{}", JSONObject.toJSONString(o));
    }

    public void sendMsg(Protocol<RequestMsg> message){
        channel.writeAndFlush(message);
    }

    public void close(){
        channel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }

}

public class NettyServerHandler extends SimpleChannelInboundHandler<Protocol<RequestMsg>> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Protocol<RequestMsg> o) throws Exception {

        logger.info("服务端收到的消息为================{}", JSONObject.toJSONString(o));
        Protocol<ResponseMsg> protocol = new Protocol<>();
        ResponseMsg responseMsg = new ResponseMsg();
        responseMsg.setResult("SUCCESS");
        responseMsg.setError("NO ERROR");
        protocol.setBody(responseMsg);
        protocol.setMsgType((short) 2);
        protocol.setId(o.getId());
        channelHandlerContext.channel().writeAndFlush(protocol);
    }
}

4、测试

复制代码
public class NettyTest {

    public static void main(String[] args) {

        new Thread(()->{
            NettyServer.startNettyServer();
        }).start();

        new Thread(()->{
            NettyClient instance = NettyClient.getInstance();
            try {
                while (true){
                    Thread.sleep(2000);
                    Protocol<RequestMsg> protocol = new Protocol<>();
                    protocol.setMsgType((short)1);
                    RequestMsg requestMsg = new RequestMsg();
                    requestMsg.setMsg("hello:"+System.currentTimeMillis());
                    requestMsg.setOther("你好啊");
                    protocol.setBody(requestMsg);
                    instance.sendMsg(protocol);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }).start();
    }
}

5、效果截图

相关推荐
最初的↘那颗心3 小时前
Java泛型深度解析:从基础语法到高级应用
java·面向对象·泛型
仙俊红3 小时前
Spring Boot `@Configuration` 与 `@Component` 笔记
java·spring boot·笔记
计算机学姐6 小时前
基于SpringBoot的社团管理系统【2026最新】
java·vue.js·spring boot·后端·mysql·spring·mybatis
天上掉下来个程小白6 小时前
微服务-25.网关登录校验-网关传递用户到微服务
java·数据库·微服务
vivi_and_qiao7 小时前
HTML的form表单
java·前端·html
Slaughter信仰7 小时前
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第四章知识点问答补充及重新排版
java·开发语言·jvm
心灵宝贝7 小时前
Mac用户安装JDK 22完整流程(Intel版dmg文件安装指南附安装包下载)
java·开发语言·macos
ta是个码农7 小时前
Mysql——日志
java·数据库·mysql·日志
今***b7 小时前
Python 操作 PPT 文件:从新手到高手的实战指南
java·python·powerpoint
David爱编程8 小时前
volatile 关键字详解:轻量级同步工具的边界与误区
java·后端