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、效果截图

相关推荐
文丑颜不良啊10 分钟前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang1 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪2 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息2 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼2 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff4 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff4 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
SL_staff5 小时前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品
nice_lcj5205 小时前
【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端
java·后端·spring·spring ai·ai应用开发
桦说编程6 小时前
TransmittableThreadLocal 解读:从 CRR 机制到上下文所有权
java·后端·源码