第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Netty 教程 Netty 教程 Netty 內(nèi)置編解碼器

Netty 內(nèi)置編解碼器

1. 前言

上節(jié)我們講解了 Netty 的內(nèi)置編碼器以及自定義編碼器,本節(jié)主要講解 Netty 提供的幾個(gè)核心編解碼器的抽象類,主要是 MessageToByteEncoderByteToMessageDecoder、SimpleChannelInboundHandler

2. 學(xué)習(xí)目的

Netty 官方也是考慮到了如何減輕開發(fā)人員的繁瑣、重復(fù)性的工作,因此,它內(nèi)置了一些好用的編解碼器抽象,讓我們更加便捷的自定義自己想要的編解碼器。

通過本節(jié)學(xué)習(xí),我們需要掌握以下幾點(diǎn)

  1. 有哪些編解碼器的抽象;
  2. 它們的核心原理是什么。

3. 類關(guān)系圖

圖片描述

4. MessageToByteEncoder

從字面意思上可知,它主要是把消息內(nèi)容轉(zhuǎn)換成 Byte,也就是說是編碼。使用非常的簡單,繼承 MessageToByteEncoder 可以很容易的開發(fā)一個(gè) Handler。

實(shí)例:

public class MyEncoder extends MessageToByteEncoder<BaseBean> {
    protected void encode(ChannelHandlerContext channelHandlerContext, 
                          BaseBean baseBean, 
                          ByteBuf byteBuf) throws Exception {
        
        //1.把“數(shù)據(jù)”轉(zhuǎn)換成字節(jié)數(shù)組
        byte[] bytes= JSON.toJSONBytes(baseBean);
		//2.把字節(jié)數(shù)組往ByteBuf容器寫
        byteBuf.writeBytes(bytes);
    }
}
ch.pipeline().addLast(new MyEncoder());

源碼:保留核心代碼

public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdapter {
    //類型匹配器
    private final TypeParameterMatcher matcher;
    //構(gòu)造函數(shù)
    protected MessageToByteEncoder(boolean preferDirect) {
        //初始化
        this.matcher = TypeParameterMatcher.find(this, MessageToByteEncoder.class, "I");
        this.preferDirect = preferDirect;
    }
    
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ByteBuf buf = null;
        if (this.acceptOutboundMessage(msg)) {
            //類型判斷通過,則處理
            
            I cast = msg;
            //創(chuàng)建ByteBuf
            buf = this.allocateBuffer(ctx, msg, this.preferDirect);
			//調(diào)用抽象方法(由子類實(shí)現(xiàn))
            this.encode(ctx, cast, buf);
        } else {
            //類型判斷不通過,則往下流轉(zhuǎn)
            ctx.write(msg, promise);
        }
    }
    //抽象方法
    protected abstract void encode(ChannelHandlerContext var1, I var2, ByteBuf var3) throws Exception;
}

5. ByteToMessageDecoder

從字面上我們也很容易猜到它的作用,主要是把 Byte 類型的數(shù)據(jù)轉(zhuǎn)換成對(duì)應(yīng)實(shí)體,也稱之為解碼。使用非常的簡單。

實(shí)例:

public class MyDecoder extends ByteToMessageDecoder {
	//把ByteBuf反序列化,并且添加到List里面
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { 
        //1.定義byte[],長度為ByteBuf可讀長度
        byte[] bytes=new byte[byteBuf.readableBytes()];
        //2.往byte[]讀取數(shù)據(jù)
        byteBuf.readBytes(bytes);
		//3.對(duì)象流
        ByteArrayInputStream is=new ByteArrayInputStream(bytes);
        ObjectInputStream iss=new ObjectInputStream(is);
        User user=(User)iss.readObject();
        //4.關(guān)閉流
        is.close();
        iss.close();
		//5.添加到集合
        list.add(user);
    }
}

繼承了 ByteToMessageDecoder 這個(gè)類之后,我們只需要實(shí)現(xiàn)一下 decode () 方法,這里的 in 大家可以看到,傳遞進(jìn)來的時(shí)候就已經(jīng)是 ByteBuf 類型,所以我們不再需要強(qiáng)轉(zhuǎn),第三個(gè)參數(shù)是 List 類型,我們通過往這個(gè) List 里面添加解碼后的結(jié)果對(duì)象,就可以自動(dòng)實(shí)現(xiàn)結(jié)果往下一個(gè) handler 進(jìn)行傳遞,我們就實(shí)現(xiàn)了解碼的邏輯 handler。

6. SimpleChannelInboundHandler

前面講解 ChannelHandler 多業(yè)務(wù)情況下的時(shí)候,我們講解到了 SimpleChannelInboundHandler,它的核心作用是自動(dòng)判斷數(shù)據(jù)格式類型,并且轉(zhuǎn)發(fā)給對(duì)應(yīng)的 Handler 來處理。

一般來說,Netty 開發(fā)的應(yīng)用如果很復(fù)雜的時(shí)候,那么應(yīng)該如何處理呢?通常有三種方案。

6.1 方案一

對(duì)反序列化后的結(jié)果進(jìn)行類型判斷,不同的類型做不同的業(yè)務(wù)處理。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
	//對(duì)反序列化后的結(jié)果進(jìn)行類型判斷,不同的類型做不同的業(yè)務(wù)處理
    if(msg instanceof LoginReqBean){
        login((LoginReqBean) msg,ctx.channel());

    }else if(msg instanceof MsgReqBean){
        sendMsg((MsgReqBean)msg,ctx.channel());
    }
}

這種模式比較簡單,但是通過 if else 邏輯進(jìn)行邏輯的處理,當(dāng)我們要處理的指令越來越多的時(shí)候,代碼會(huì)顯得越來越臃腫。

6.2 方案二

判斷是否是自己應(yīng)該處理,如果不是,則手工往下流轉(zhuǎn)。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if(msg instanceof LoginReqBean){
        //業(yè)務(wù)處理
        
    }else{
        //往下流轉(zhuǎn)
        ctx.fireChannelRead(msg);
    }
}

6.3 方案三

使用 SimpleChannelInboundHandler 來簡化我們的指令處理邏輯。

SimpleChannelInboundHandler 使用非常簡單,我們在繼承這個(gè)類的時(shí)候,給他傳遞一個(gè)泛型參數(shù),然后在 channelRead0 () 方法里面,我們不用再通過 if 邏輯來判斷當(dāng)前對(duì)象是否是本 handler 可以處理的對(duì)象,也不用強(qiáng)轉(zhuǎn),不用往下傳遞本 handler 處理不了的對(duì)象,這一切都已經(jīng)交給父類 SimpleChannelInboundHandler 來實(shí)現(xiàn)了,我們只需要專注于我們要處理的業(yè)務(wù)邏輯即可。

實(shí)例:

public class LoginReqHandler extends SimpleChannelInboundHandler<LoginReqBean> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, LoginReqBean loginReqBean){
        //登錄邏輯
    }
}
public class MsgReqHandler extends SimpleChannelInboundHandler<MsgReqBean> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MsgReqBean msgReqBean){
        //消息發(fā)送邏輯
    }
}

源碼:只保留核心部分

public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter {
    //類型匹配器
    private final TypeParameterMatcher matcher;
    
    protected SimpleChannelInboundHandler(boolean autoRelease) {
        //初始化類型匹配器
        this.matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I");
    }
    
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (this.acceptInboundMessage(msg)) {
            //類型校驗(yàn)通過通過,則調(diào)用抽象方法(子類去實(shí)現(xiàn))
            this.channelRead0(ctx, msg);
        } else {
            //類型校驗(yàn)不通過,則往下流轉(zhuǎn)
            ctx.fireChannelRead(msg);
        }
    }
    
    //抽象方法,由自定義業(yè)務(wù)類去實(shí)現(xiàn)
    protected abstract void channelRead0(ChannelHandlerContext var1, I var2) throws Exception;
}

7. 小結(jié)

本節(jié)學(xué)習(xí)主要掌握以下知識(shí)點(diǎn)

  1. 基于 MessageToByteEncoder,我們可以實(shí)現(xiàn)自定義編碼,而不用關(guān)心 ByteBuf 的創(chuàng)建,不用每次向?qū)憯?shù)據(jù)的時(shí)候,都手工進(jìn)行編碼;
  2. 基于 ByteToMessageDecoder,我們可以實(shí)現(xiàn)自定義解碼,而不用關(guān)心 ByteBuf 的強(qiáng)轉(zhuǎn)和 解碼結(jié)果的傳遞;
  3. 基于 SimpleChannelInboundHandler,我們可以實(shí)現(xiàn)根據(jù)數(shù)據(jù)格式來判斷由哪個(gè) Handler 去處理,不需要手工 if else 判斷,不需要手動(dòng)傳遞對(duì)象,做到了真正關(guān)心業(yè)務(wù)邏輯的處理;
  4. 其實(shí),這三種 Handler 也是有各自的應(yīng)用場景,ByteToMessageDecoderMessageToByteEncoder 是用來封裝解碼器和編碼器,SimpleChannelInboundHandler 則是用于業(yè)務(wù)邏輯的簡化開發(fā)。