❃博主首页 :

「码到三十五」 ,同名公众号 :「码到三十五」

♝博主的话 :

搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的coder,一起筑基



Netty是一个高性能的网络编程框架,它提供了丰富的编解码器(Encoder/Decoder)来简化网络数据的处理。在Netty中,MessageToMessageEncoder类是一个关键的编码器组件,它用于将业务消息对象编码为字节流或其他形式的消息,以便在网络中传输。本文将结合Netty的源码,详细分析MessageToMessageEncoder类的工作原理、实现细节以及使用场景。

文章目录
  • 一、MessageToMessageEncoder类概述
  • 二、源码解析
  • 三、工作原理
  • 四、使用场景
  • 五、注意事项
  • 六、结语

一、MessageToMessageEncoder类概述

MessageToMessageEncoder是Netty提供的一个抽象类,它继承自ChannelOutboundHandlerAdapter。这个类的主要作用是将业务消息对象编码为另一种形式的消息(通常是字节流),并将编码后的消息传递给下一个ChannelOutboundHandler进行发送。

二、源码解析

首先,我们来看一下MessageToMessageEncoder的核心源码结构。

public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerAdapter {
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        // 检查是否是可接受的消息类型
        if (acceptOutboundMessage(msg)) {
            // 调用encode方法进行编码
            List<Object> encoded = encode(ctx, msg, List.of(promise));
            if (encoded == null || encoded.isEmpty()) {
                // 如果没有编码后的消息,则释放原始消息
                ReferenceCountUtil.release(msg);
                promise.setSuccess();
            } else {
                // 如果有编码后的消息,则逐个写入
                for (Object e : encoded) {
                    ctx.write(e, promise);
                }
            }
        } else {
            // 如果不是可接受的消息类型,则传递给下一个ChannelOutboundHandler
            ctx.write(msg, promise);
        }
    }

    // ... 其他方法和字段

    protected abstract List<Object> encode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;

    // 辅助方法,用于检查是否是可接受的消息类型
    protected boolean acceptOutboundMessage(Object msg) throws Exception {
        return findEncoder(msg) != null;
    }

    // 辅助方法,用于查找编码器
    private Encoder<I> findEncoder(Object msg) {
        // 实际上,这个方法是抽象的,需要在子类中实现
        // 这里只是表示一个概念,实际源码中可能没有这个方法
        // 子类通常会在acceptOutboundMessage方法中直接判断msg的类型
        return null;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.

注意:实际源码中findEncoder方法并不存在,acceptOutboundMessage方法通常由子类实现,以判断消息是否可以被编码。

从源码中可以看出,MessageToMessageEncoder的核心方法是encode,它是一个抽象方法,需要子类来实现。在write方法中,MessageToMessageEncoder首先检查消息是否是可接受的类型(通过acceptOutboundMessage方法),然后调用encode方法进行编码。编码后的消息会被逐个写入到网络中。

三、工作原理
  1. 编码过程
  • 当有消息需要发送时,Netty会调用MessageToMessageEncoderwrite方法。
  • write方法内部会首先检查消息是否是可接受的类型(这一步是可选的,取决于子类是否实现了acceptOutboundMessage方法)。
  • 如果消息是可接受的,write方法会调用encode方法进行编码。
  • 编码过程中,子类实现的encode方法会根据具体的协议逻辑将业务消息对象编码为另一种形式的消息(通常是字节流),并将编码后的消息添加到传入的List<Object>中。
  • 编码完成后,编码后的消息会被逐个写入到网络中。
四、使用场景

MessageToMessageEncoder适用于需要将业务消息对象编码为字节流或其他形式的消息以便在网络中传输的场景。例如,在处理HTTP请求时,可以使用MessageToMessageEncoder将HTTP请求对象编码为字节流,以便发送给HTTP服务器。

五、注意事项
  1. 线程安全MessageToMessageEncoder本身不是线程安全的。如果你的编码逻辑涉及到共享资源的访问或修改,需要确保这些操作是线程安全的。
  2. 性能考虑:在编码过程中,MessageToMessageEncoder可能会创建新的消息对象,这可能会带来一定的内存开销。因此,在使用MessageToMessageEncoder时,需要权衡其带来的便利和可能的性能开销。
  3. 异常处理:在编码过程中,如果发生异常,需要妥善处理,例如记录日志、关闭连接等。
六、结语

MessageToMessageEncoder是Netty中用于处理消息编码过程的重要工具。通过提供一个抽象的编码框架,它使得开发者可以更容易地编写基于消息的协议编码逻辑。希望本文能够帮助开发者更好地理解MessageToMessageEncoder类的工作原理和使用方法,并在实际开发中充分利用其提供的便利。


关注公众号[码到三十五]获取更多技术干货 !