java netty之MessageToByteEncoder

【Netty4】自定义编码解码器ByteToMessageDecoder、MessageToByteEncoder 文章目录1. 概述2. 代码2.1 MyMessageEncoder自定义编码器2.2 MyMessageDecoder自定义解码器2.3 自定义协议包2.4 服务端代码2.5 客户端代码2.6 执行 系列文章: 《粘包拆包样例 & DelimiterBasedFrameDecoder》 《自定义编码解码器ByteToMessageDecoder、MessageToByteEncoder》 1. 概述 经过《粘包拆包样例 & DelimiterBasedFrameDecoder》,我们知道什 阅读详情

上面的文章已经说过了decoder,它的用处是将读取的byte数据转化为用户自己定义的数据类型

这一篇文章要说的encoder,它的作用与前面提到的decoder就相反了,用于将用户定义的类型转化为byte类型,这样才能通过channel发送出去。。。

我们还是先来看看它的继承体系吧:


可以看到它继承自messageadapter,这种类型我们在前面已经有过说明,adapter的作用就是比较粗糙的实现方法,用户可以继承它然后重写自己感兴趣的方法,

而且在前面我们知道在pipeline上面调用write方法的时候,netty会从pipeline的后面向前寻找合适的outboundhandler用于处理要写的数据,而且是先将数据存放到handler的buffer里面,真正的写数据则是调用flush方法实现的。。。

首先我们要来看看这里将会调用的flush方法:

    @Override
    public final void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
        ChannelHandlerUtil.handleFlush(ctx, promise, isCloseOnFailedFlush(), this);
    }
这里调用了ChannelHandlerUtil的flush方法,我们再来看看这个方法是具体怎么实现的吧:


    public static <T> void handleFlush(
            ChannelHandlerContext ctx, ChannelPromise promise, boolean closeOnFailedFlush,
            SingleOutboundMessageHandler<T> handler) throws Exception {

        MessageBuf<Object> in = ctx.outboundMessageBuffer();  //取得当前outbuffer
        final int inSize = in.size();
        if (inSize == 0) {
            ctx.flush(promise);
            return;
        }

        int processed = 0;
        try {
            if (!handler.beginFlush(ctx)) {
                throw new IncompleteFlushException(
                        "beginFlush(..) rejected the flush request by returning false. " +
                        "none of " + inSize + " message(s) fulshed.");
            }
            for (;;) {  //一个for循环将数据全部都取出来
                Object msg = in.poll();
                if (msg == null) {
                    break;
                }

                if (!handler.acceptOutboundMessage(msg)) {
                    addToNextOutboundBuffer(ctx, msg);
                    processed ++;
                    continue;
                }

                @SuppressWarnings("unchecked")
                T imsg = (T) msg;
                try {
                    handler.flush(ctx, imsg);  //这里将会调用用户定义的flush方法,将message转化为byte类型存到下一个handler
                    processed ++;
                } finally {
                    BufUtil.release(imsg);
                }
            }
        } catch (Throwable t) {
            IncompleteFlushException pfe;
            if (t instanceof IncompleteFlushException) {
                pfe = (IncompleteFlushException) t;
            } else {
                String msg = processed + " out of " + inSize + " message(s) flushed";
                if (t instanceof Signal) {
                    Signal abort = (Signal) t;
                    abort.expect(ABORT);
                    pfe = new IncompleteFlushException("aborted: " + msg);
                } else {
                    pfe = new IncompleteFlushException(msg, t);
                }
            }
            fail(ctx, promise, closeOnFailedFlush, pfe);
        }

        try {
            handler.endFlush(ctx);
        } catch (Throwable t) {
            if (promise.isDone()) {
                logger.warn("endFlush() raised a masked exception due to failed flush().", t);
            } else {
                fail(ctx, promise, closeOnFailedFlush, t);
            }
        }

        if (!promise.isDone()) {
            ctx.flush(promise);   //这里又会向上寻找outboundhandler,把数据flush出去,这里最终将会找到pipeline上面默认的headerhandler
        }
    }

上面的代码将会调用MessageToByteEncoder类型的flush方法,这个方法将会调用用户定义的encode方法,用于将数据写到下一个handler的buffer里面,最终还会调用当前handler,也就是encoder的context的flush方法,将会向上寻找outboundhandler的flush方法,其实最终会找到默认的headerhandler。。。。

好吧,我们来看看MessageToByteEncoder类型的flush方法的实现吧:
    @Override
    public void flush(ChannelHandlerContext ctx, I msg) throws Exception {
        try {
          //这里是写到下一个handler的outbuffer里面去
            encode(ctx, msg, ctx.nextOutboundByteBuffer());
        } catch (CodecException e) {
            throw e;
        } catch (Exception e) {
            throw new CodecException(e);
        }
    }

这里调用了用户定义的encode方法,不过需要注意的是这里传进去的buffer是下一个outboundhandler的outbuf,这里在复习一下前面的知识:

(1)operationhandler相关的动作都是从pipeline的后面向前进行handler的调用的

(2)在pipeline的最前面有一个netty默认的outboundhandler,它用于真正的将数据发送出去,它里面会包含一个unsafe对象,这个unsafe对象就是所属的channel的unsafe对象,最终会调用这个unsafe对象的相关方法将数据发送出去。。


如果我们要自己编写encoder,那么最终pipeline的构成如下图:


这样,当我们直接调用pipeline的write方法写我们自定义的类型的对象的时候,数据首先是写到了我们自己定义的encoder,然后当flush的时候,decoder会调用我们自己定义的方法将这些数据转化为byte类型,保存到默认的outboundhandler的buffer里面,然后再由其将数据发送出去


好了那么整个encode的流程也就走通了。。

解析SAP移动类型与总账科目字段选择冲突:以Z21和8051010100为例 本文深入解析了SAP系统中移动类型与总账科目字段选择冲突的根源与解决方案。以移动类型Z21和科目8051010100为例,当两者对“供应商货物移动”字段的要求(必填与隐藏)不一致时,系统会报错M7093。文章详细介绍了如何使用标准报表RM07CUFA进行精确诊断,并提供了通过调整字段状态组或移动类型配置来消除矛盾的实用方法。 阅读详情

相关推荐

SAP-FI:SAP财务会计常用事务码详解

SAP-FI:SAP财务会计常用事务码详解

baidu_35680696的博客 1936

吃透Netty源码系列四十一之MessageToByteEncoder详解

吃透Netty源码系列四十一之MessageToByteEncoder详解MessageToByteEncoderTypeParameterMatcher空类型参数匹配get获取类型参数匹配器ReflectiveMatcherfind寻找泛型对应的匹配器find0图示结构显示构造函数隐式构造函数write写方法allocateBuffer申请缓冲区最简单的例子 MessageToByteEncod...

王伟王胖胖的博客 5628

SAP-MM-发票校验-外币PO的发票校验

固定汇率:如果勾选了,那发票校验时,就按这个汇率来做发票校验,不允许更改,也就不会有汇率差异了,如果不勾选,则发票校验时,会取MIRO界面上的凭证类型的默认汇率类型对应的即时汇率;上图标红色的是发票校验时的汇率,默认是从凭证类型的默认汇率类型对应的即时汇率中取值,比如以上图为例,就是。种方式是把总的差异在汇率差异和价格差异之间做分配,两个差异的过账方式也是不一样的;,那发票校验时可能存在汇率差异,这个汇率差异系统用多种处理方式;,那这里就要再指定一个汇率类型,作为计算汇率差异的依据;

yanzibing99的博客 3214

Netty之MessageToByteEncoder

Netty提供了一个特殊的ChannelHandler来专门处理编码逻辑,不需要每一次将响应写到对端的时候都调用一次编码逻辑进行编码,也不需要自行创建ByteBuf。这个类被叫作MessageToByteEncoder,从字面意思可以看出,它的功能就是将对象转换到二进制数据。 使用MessageToByteEncoder来实现编码逻辑的过程如下。 PacketEncoder继承自MessageToByteEncoder,泛型参数Packet表示这个类的作用是实现Packet类型对象到二进制.

zsj777的专栏 1362

SAP FICO凭证过账接口开发实战:避坑指南与ABAP实现

会计凭证过账是企业财务系统集成的核心环节,其本质是将业务单据按会计准则、科目体系和风控规则转化为SAP FICO可识别的结构化数据。理解凭证头(BKPF)与行项目(BSEG)的数据结构、多币种汇率处理、未清项管理逻辑,是保障过账成功的技术基础。SAP标准BAPI_ACC_DOCUMENT_POST在高并发场景下存在锁竞争与隐式事务风险,生产环境更推荐基于RFC调用底层过账函数并自主控制事务边界。结合配置驱动映射、最小字段集设计与精细化错误日志,可构建高可用、易维护、可审计的FICO集成接口,广泛应用于MES

weixin_33912246的博客 347

SAP销售凭证详解:类型、配置与凭证流实战

在企业销售业务中,销售订单、交货单、发票等单据的流转构成了订单履约的主线。SAP SD模块正是通过销售凭证(Sales Document)体系将这些业务节点串联起来,实现从询价、订单到开票的全流程管理。理解销售凭证类型、项目类别与计划行类别的配置逻辑,是掌握SAP SD的关键。销售凭证不仅承载客户需求与价格信息,更驱动后续交货、发货、开票等动作,并形成完整凭证流,支撑追溯与分析。基于此,本文围绕销售凭证的类型体系、配置思路、主链路操作(如VA01、VL01N、VF01)以及常见增强与排障实践展开,结合工程经

weixin_33994429的博客 401

【Netty入门03】 Netty编解码器

只要是需要跟其他节点传输数据的应用程序都需要定义如何解析两个节点之间传输的原始数据,以及如何将其转换成目标程序所需要的数据格式(例如由二进制转换为Java对象)。这种转换逻辑就是交由编解码器处理。编解码器由编码器和解码器组成,解码器负责将消息从字节或其他序列形式转成指定的消息对象,而编码器则将消息对象转成字节或其他序列形式以便在网络上传输。

qq_40720500的博客 832

SAP销售开票流程全解析:从业务到财务的自动化集成

销售开票是企业财务流程中的关键环节,它基于事件驱动原理,在业务发生后自动触发。其核心价值在于实现物流、信息流与资金流的三流合一,确保收入确认的合规性与准确性。通过系统集成,开票流程能自动完成定价计算、税务处理及财务过账,大幅提升运营效率并降低人工差错。在SAP等ERP系统中,这一流程深度集成了销售与财务模块,涉及开票凭证、定价过程、输出管理等关键技术组件,广泛应用于制造业、零售业等需要高效处理‘订单到现金’循环的行业场景。本文聚焦SAP销售开票,深入剖析其标准流程、配置逻辑与实操要点,帮助读者掌握从发货过账

weixin_33910460的博客 882

高性能IO框架Netty五 - Netty内置的编解码器

目录 一、什么是编解码器 二、解码器 2.1ByteToMessageDecoder 2.2MessageToMessageDecoder 2.3 TooLongFrameException 三、编码器 3.1 MessageToByteEncoder 3.2 MessageToMessageEncoder 四、编解码器类 五、Netty内置的编解码器和ChannelH...

b379685397的博客 1万+

SAP财务顾问必备:手把手教你配置FI模块凭证相关设置(含OB41/OBA7事务码详解)

本文深入解析SAP FI模块中凭证相关配置,涵盖凭证类型定义(OBA7)、过账码配置(OB41)等关键事务码的实战应用。通过详细步骤和最佳实践,帮助SAP财务顾问高效配置财务凭证系统,提升企业财务数据处理效率和准确性。

pp12345的博客 270

SAP 移动类型总览

SAP 移动类型总览

m0_56573334的博客 9201

SAP FI新手必看:客户预收款和汇票业务,用特别总账标记A和W怎么配?

本文深入解析SAP FI模块中特别总账标记A和W的应用,涵盖客户预收款和汇票业务的配置与操作。通过详细步骤和实战案例,帮助新手掌握统驭科目与客户主数据的关联设置,提升财务核算效率和准确性。

weixin_30654583的博客 198

SAP统驭科目本质:财务与业务数据一致性的技术锚点

统驭科目是ERP系统中实现财务与业务数据实时一致的核心机制,其原理在于通过强制映射(如客户/供应商/资产主数据与总账科目的双向绑定),确保总账余额与业务明细动态同步。该机制并非简单汇总工具,而是基于SAP‘业务驱动财务’架构设计的控制逻辑,具备不可绕过、不可手工篡改、明细分离存储等技术特性。其核心价值在于支撑审计合规、自动化对账与跨模块数据溯源,在应付账款、应收账款、固定资产等关键场景中直接决定账实相符性。本文深入解析统驭科目在SAP FICO中的配置逻辑、过账行为与典型故障根因。

weixin_34221276的博客 310

超越基础配置:深度解析SAP销售凭证类型(TVAK)与下游单据的联动关系(以BOR1分配BF2为例)

本文深入解析SAP销售凭证类型(TVAK)与下游单据的联动关系,以BOR1分配BF2为例,探讨销售凭证类型配置背后的业务逻辑和系统联动机制。通过实际案例,详细介绍了凭证类型在业务场景合规性、流程路径选择和系统行为控制中的核心作用,帮助顾问提升配置深度与业务理解。

weixin_30482383的博客 361

SAP FB02凭证修改保姆级配置指南:避开OB32和TBAER表的那些坑

本文详细解析SAP FB02凭证修改的配置流程与常见问题,涵盖OB32和TBAER表的关键设置,帮助用户避开配置陷阱。通过三层控制体系解析、高级排查技巧及典型场景解决方案,提升会计凭证修改效率与准确性。

weixin_30751947的博客 483

SAP采购收货库存金额与会计凭证全链路解析

在SAP ERP项目实施与报表开发中,物料凭证与会计凭证的关联始终是MM模块和FI模块集成绕不开的环节。采购收货(移动类型101)看似只是一次过账,实际会同时更新物料凭证(MKPF/MSEG)、库存数量表(MARD/MCHB/MSKU)、采购订单历史(EKBE),并基于OBYC科目确定逻辑自动生成会计凭证。理解库存数量与库存金额分表管理、标准价与移动平均价的差异处理,以及BKPF-AWKEY作为物料凭证到FI凭证的桥梁,是进行对账和二次开发的关键。本文从基础表结构讲起,逐步拆解101收货的凭证流、科目确定规

weixin_29913663的博客 299

SD销售订单退货,冲销,拆分开票,借贷凭证操作笔记

一、 退货业务操作与建立订单大体相似,订单类型为RE,拒绝原因须填写, VA01退货单建立——VL01交货订单建立——VL02交货订单维护(工厂,拣配数量,货物金额进行确认;有的可能要进入质量管理)——交货过账——VF01发票建立——VF02发票维护(确认开票金额,数量)——小绿旗——凭证流查看会计分录 VA01退货单建立 会计明细 会计分录:借:应交税费            ...

SAP之路 1万+

SAP发票校验BAPI实战:MIRO核心函数PARK与RELEASE

在企业的信息化管理中,发票校验是财务与采购流程中的关键环节,尤其在SAP等ERP系统中,如何实现自动化处理成为焦点。SAP提供了标准BAPI接口来支撑该场景,其中BAPI_INCOMINGINVOICE_PARK与BAPI_INCOMINGINVOICE_RELEASE是核心组件。它们遵循“预制”与“过账”分离的设计原理,既保证了数据处理的灵活性,又降低了错误风险。通过ABAP编程,开发者可将这些接口集成至业务系统,实现发票数据的自动校验与过账。本篇文章聚焦MIRO发票校验的BAPI实现,详细解析参数配置、

weixin_29597551的博客 301
上一篇: 红黑树--java TreeMap
下一篇: java ThreadLocal与其应用(netty)
fjs_cloud
博客等级 码龄15年 248粉丝 192原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值