欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Netty如何自定義編碼解碼器

 更新時間:2025年03月06日 10:35:31   作者:帥氣的人123  
Netty自定義編碼解碼器:InboundHandler處理入棧數(shù)據(jù),OutboundHandler處理出棧數(shù)據(jù),解碼器繼承ByteToMessageDecoder,編碼器繼承MessageToByteEncoder,ReplayingDecoder簡化了解碼邏輯,但可能因異常重試導(dǎo)致性能下降

Netty 自定義編碼解碼器

入棧:InboundHandler ,出棧:OutboundHandler。Netty 構(gòu)建 chain 來處理業(yè)務(wù)。

自定義一個解碼器

解碼器主要是對客戶端發(fā)送的消息進(jìn)行解碼處理,所以他是一個入棧的處理器,因此他會有一個入棧的標(biāo)識ibound=true;

解碼器一般我都們都會基層 Netty 提供給的一個實(shí)現(xiàn)類來實(shí)現(xiàn)自己的解碼邏輯 -> io.netty.handler.codec.ByteToMessageDecoder 這就是解碼的抽象類,默認(rèn)我們要實(shí)現(xiàn)一個抽象方法

com.netty.codec.custom.InboundAndOutboundHandler#decode 

這個方法有大概三個參數(shù);

  • ChannelHandlerContext channelHandlerContext 這個是上下文信息,可以獲取通道管道等信息。
  • ByteBuf byteBuf 客戶端發(fā)送的消息就是存在這個參數(shù)的對象里面我們要通過這個對象的read***方法讀取我們需要的數(shù)據(jù)類型,可以是 Long,Byte 等類型的數(shù)據(jù)然后我們可以就可以轉(zhuǎn)換成為我們需要的格式。
  • List<Object> list 集合,將解碼后的數(shù)據(jù)傳遞給下一個inboundHandler 處理類。

代碼示例

@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) {
    // Long => 8 byte
    if (byteBuf.readableBytes() >= 8) {
        list.add(byteBuf.readLong());
    } else log.warn("字節(jié)數(shù)異常 => {}", byteBuf.readableBytes());
}

這樣我們就實(shí)現(xiàn)了一個簡單的解碼器。

自定義一個編碼器

解碼器主要是對服務(wù)端將要發(fā)送給客戶端的消息進(jìn)行編碼處理,所以他是一個出棧的處理器,因此他會有一個入棧的標(biāo)識outbound=true;

使用 Netty 提供的抽象類 => io.netty.handler.codec.MessageToByteEncoder<T> 泛型 T 表示你要發(fā)送的消息的類型,實(shí)現(xiàn)抽象方法 => com.netty.codec.custom.OutboundHandler#encode 方法的參數(shù)有三個:

  • ChannelHandlerContext channelHandlerContext 這個是上下文信息,可以獲取通道、管道等信息。
  • Long msg 服務(wù)端要發(fā)送給客戶端的消息
  • ByteBuf byteBuf

代碼示例

@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Long msg, ByteBuf byteBuf) {
    byteBuf.writeLong(msg);
    log.info("發(fā)送消息成功");
}

后續(xù) -> io.netty.handler.codec.ReplayingDecoder

ByteToMessage 其實(shí)在使用過程中會遇到一些問題,例如:

當(dāng)我們的解碼器中想要將字節(jié)轉(zhuǎn)換為一個 Integer ,我們知道 Integer 是四個字節(jié)的,但是如果在讀取的時候不夠四個字節(jié),這個時候我們就需要做一些判斷邏輯 => if (byteBuf.readableBytes() >= 4) 當(dāng)這個返回值為 true 的時候我么就可以繼續(xù)執(zhí)行解碼的邏輯。

那我們怎么可以跳過這一步不判斷直接進(jìn)行我們的轉(zhuǎn)換邏輯呢?

這個時候就可以使用 Netty 的

io.netty.handler.codec.ReplayingDecoder

可以不用判斷可讀字節(jié)數(shù)的原理:

ReplayingDecoderByteToMessage 的子類,源碼如下:

public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
    ...
}

ReplayingDecoder 的秘密就是對 ByteToMessageCallDecode(...) 方法的重寫,觀摩一下具體實(shí)現(xiàn):

@Override
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
    replayable.setCumulation(in);
    try {
        while (in.isReadable()) {
            int oldReaderIndex = checkpoint = in.readerIndex();
            int outSize = out.size();

            if (outSize > 0) {
                fireChannelRead(ctx, out, outSize);
                out.clear();

                // Check if this handler was removed before continuing with decoding.
                // If it was removed, it is not safe to continue to operate on the buffer.
                //
                // See:
                // - https://github.com/netty/netty/issues/4635
                if (ctx.isRemoved()) {
                    break;
                }
                outSize = 0;
            }

            S oldState = state;
            int oldInputLength = in.readableBytes();
            try {
                decodeRemovalReentryProtection(ctx, replayable, out);

                // Check if this handler was removed before continuing the loop.
                // If it was removed, it is not safe to continue to operate on the buffer.
                //
                // See https://github.com/netty/netty/issues/1664
                if (ctx.isRemoved()) {
                    break;
                }

                if (outSize == out.size()) {
                    if (oldInputLength == in.readableBytes() && oldState == state) {
                        throw new DecoderException(
                                StringUtil.simpleClassName(getClass()) + ".decode() must consume the inbound " +
                                "data or change its state if it did not decode anything.");
                    } else {
                        // Previous data has been discarded or caused state transition.
                        // Probably it is reading on.
                        continue;
                    }
                }
            } catch (Signal replay) {
                replay.expect(REPLAY);

                // Check if this handler was removed before continuing the loop.
                // If it was removed, it is not safe to continue to operate on the buffer.
                //
                // See https://github.com/netty/netty/issues/1664
                if (ctx.isRemoved()) {
                    break;
                }

                // Return to the checkpoint (or oldPosition) and retry.
                int checkpoint = this.checkpoint;
                if (checkpoint >= 0) {
                    in.readerIndex(checkpoint);
                } else {
                    // Called by cleanup() - no need to maintain the readerIndex
                    // anymore because the buffer has been released already.
                }
                break;
            }

            if (oldReaderIndex == in.readerIndex() && oldState == state) {
                throw new DecoderException(
                       StringUtil.simpleClassName(getClass()) + ".decode() method must consume the inbound data " +
                       "or change its state if it decoded something.");
            }
            if (isSingleDecode()) {
                break;
            }
        }
    } catch (DecoderException e) {
        throw e;
    } catch (Exception cause) {
        throw new DecoderException(cause);
    }
}

實(shí)現(xiàn)不需要判斷的邏輯就是因為

int oldReaderIndex = checkpoint = in.readerIndex(); 

如果在執(zhí)行過程中出現(xiàn)異常就會在代碼中重置 index

總結(jié)

雖然 ReplayingDecoder節(jié)約了判斷的邏輯,但是從他的代碼實(shí)現(xiàn)邏輯看到是通過拋出異常來不斷的重試,所以在某些特殊的情況下會造成性能的下降。所以還是再選擇的時候要根據(jù)自己的實(shí)際需求來判斷是使用 ByteToMessage 還是使用 ReplayingDecoder

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java如何獲取數(shù)組和字符串的長度(length還是length())

    Java如何獲取數(shù)組和字符串的長度(length還是length())

    這篇文章主要介紹了Java如何獲取數(shù)組和字符串的長度(length還是length()),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Spring MVC的web.xml配置詳解

    Spring MVC的web.xml配置詳解

    這篇文章主要介紹了Spring MVC的web.xml配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • java教程之java注解annotation使用方法

    java教程之java注解annotation使用方法

    這篇文章主要介紹了java注解annotation使用方法,注解可以定義到方法上,類上,一個注解相當(dāng)與一個類,就相當(dāng)于實(shí)例了一個對象,加上了注解,就相當(dāng)于加了一個標(biāo)志
    2014-01-01
  • Java 設(shè)計模式原則之迪米特法則詳解

    Java 設(shè)計模式原則之迪米特法則詳解

    這篇文章主要介紹了Java 設(shè)計模式原則之迪米特法則詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 通過JDK源碼角度分析Long類詳解

    通過JDK源碼角度分析Long類詳解

    這篇文章主要給大家介紹了關(guān)于通過JDK源碼角度分析Long類的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用long類具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • IDEA整合SSM框架實(shí)現(xiàn)網(wǎng)頁上顯示數(shù)據(jù)

    IDEA整合SSM框架實(shí)現(xiàn)網(wǎng)頁上顯示數(shù)據(jù)

    最近做了個小項目,該項目包在intellij idea中實(shí)現(xiàn)了ssm框架的整合以及實(shí)現(xiàn)訪問,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • JAVA實(shí)現(xiàn)長連接(含心跳檢測Demo)

    JAVA實(shí)現(xiàn)長連接(含心跳檢測Demo)

    這篇文章主要介紹了JAVA實(shí)現(xiàn)長連接(含心跳檢測Demo),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • idea插件之如何使用JarEditor編輯Java JAR文件

    idea插件之如何使用JarEditor編輯Java JAR文件

    JarEditor是一款用于在IntelliJIDEA中直接編輯JAR文件的插件,支持反編譯查看和編輯.class文件,并提供即時編譯與保存功能,通過JarEditor,用戶可以在IDE內(nèi)一站式完成JAR文件的編輯、管理和打包操作,提高開發(fā)效率,但在生產(chǎn)環(huán)境中使用前,請確保備份并測試修改
    2025-01-01
  • eclipse配置javap命令的方法

    eclipse配置javap命令的方法

    本篇文章主要介紹了如何為eclipse配置javap命令,在配置過程中會出現(xiàn)的小問題的解決方法,非常實(shí)用,需要的朋友可以參考下
    2015-07-07
  • java方法實(shí)現(xiàn)簡易ATM功能

    java方法實(shí)現(xiàn)簡易ATM功能

    這篇文章主要為大家詳細(xì)介紹了用java方法實(shí)現(xiàn)簡易ATM功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04

最新評論