天天看點

Netty5使用者手冊之六:netty核心之ChannelHandler用法詳解

概述

      主要介紹四個主要的核心類:ChannelPipeline、ChannelHandlerContext、ChannelHandler、Inbound VS Outbound(入站和出站)等。netty提供了強大的類來處理輸入和輸出的資料,通過ChannelHandler可以快速編寫出可重用的、高性能的代碼程式。下面一一介紹這些核心類的用法:

ChannelPipeline類的用法

       ChannelPipeline類是ChannelHandler執行個體對象的清單,用于處理或截獲通道的接收和發送資料。它提供了一種進階的截取過濾模式(類似serverlet中的filter功能),讓使用者可以在ChannelPipeline中完全控制一個事件以及如何處理ChannelHandler與ChannelPipeline的互動.        對于每個新的通道Channel,都會建立一個新的ChannelPipeline,并将器pipeline附加到channel中。一旦連接配接,channel和它之間的聯系就會建立起來。通道Channel不能附加其他的pipeline或與pipeline分離開。        下圖描述了ChannelHandler通道處理器類與pipeline中的io處理關系,一個io操作可以由一個ChannelInboundHandler或ChannelOutboundHandle進行處理,并通過調用ChannelInboundHandler處理入站io或通過ChannelOutboundHandler處理出站IO。

Netty5使用者手冊之六:netty核心之ChannelHandler用法詳解

        如上圖,ChannelPipeline是ChannelHandler的一個清單,如果一個入站io事件發生,這個事件會從第一個開始依次通過每裡面的channelhandler;如果是一個出站io事件,則會從最後一個開始依次通過channelhandler。         ChannelPipeline可以動态添加、删除、替換其中的ChannelHandler,這樣的機制可以提高靈活性。

        修改ChannelPipeline的方法:

• addFirst(...),添加ChannelHandler在ChannelPipeline的第一個位置

• addBefore(...),在ChannelPipeline中指定的ChannelHandler名稱之前添加ChannelHandler

• addAfter(...),在ChannelPipeline中指定的ChannelHandler名稱之後添加ChannelHandler

• addLast(ChannelHandler...),在ChannelPipeline的末尾添加ChannelHandler

• remove(...),删除ChannelPipeline中指定的ChannelHandler

• replace(...),替換ChannelPipeline中指定的ChannelHandler

1.	ChannelPipeline pipeline = ch.pipeline();  
2.	FirstHandler firstHandler = new FirstHandler();  
3.	pipeline.addLast("handler1", firstHandler);  
4.	pipeline.addFirst("handler2", new SecondHandler());  
5.	pipeline.addLast("handler3", new ThirdHandler());  
6.	pipeline.remove("“handler3“");  
7.	pipeline.remove(firstHandler);  
8.	pipeline.replace("handler2", "handler4", new FourthHandler());<span style="font-family:Microsoft YaHei;font-size:14px;">
</span>
           

ChannelHandlerContext類的用法

      每個ChannelHandler被添加到ChannelPipeline中後,都會建立一個ChannelHandlerContext類添加到ChannelHandler中,此context允許ChannelHandler與其他ChannelHandler進行互動,這是對同一個pipeline而言的。io事件通過contxt将事件傳入到pipeline中的下一個channelhandler中,如下圖:

Netty5使用者手冊之六:netty核心之ChannelHandler用法詳解

ChannelHandler以及子類

      Netty中有3個實作了ChannelHandler接口的類,其中2個是接口(ChannelInboundHandler用來處理入站資料也就是接收資料、ChannelOutboundHandler用來處理出站資料也就是寫資料),一個是抽象類ChannelHandlerAdapter類。       ChannelHandler提供了在它的生命周期内添加或從ChannelPipeline中删除的方法:       1.handlerAdded:ChannelHandler添加到實際上下文中準備處理事件。       2.handlerRemoved:将ChannelHandler從實際上下文中删除,不再處理事件。       3.exceptionCaught:處理跑出的異常。       這三個方法都需要傳遞ChannelHandlerContext參數對象,每個ChannelHandler被添加到Channelpipeline時會自動建立ChannelHandlerContext。       Netty還提供了一個實作了ChannelHandler的抽象類:ChannelHandlerAdapter類。他實作了父類的所有方法,基本上就是傳遞事件到pipeline中的下一個ChannelHandler直到結束。

ChannelInboundHandler類的用法

       它提供了一些方法來接收資料或Channel狀态改變時被調用,下面是一些常用方法:        1.channelRegistered:ChannelHandlerContext的Channel被注冊到EventLoop中。        2.channelUnregistered:ChannelHandlerContext的channel從eventloop中登出。        3.channelActive方法:ChannelHandlerContext的channel已被激活。        4.channelInactive方法:ChannelHandlerContext的channel結束生命周期。        5.channelRead方法:從目前Channel的對端讀取消息。        6.channelReadComplete方法:消息讀取完畢有執行。        7.userEventTriggered方法:一個使用者事件被觸發。        8.channelWritabilityChanned方法:改變通道的可寫狀态,可以使用Channel.isWritable檢查。        9.exceptionCaught,重寫父類ChannelHandler的方法,處理異常.        Netty提供了一個實作了ChannelInboundHandler接口并繼承ChannelHandlerAdapter的類:ChannelnboundHandlerAdapter。它實作了ChannelInboundHandler所有的方法,作用就是處理消息并将消息轉發到ChannelPipeline中的下一個channelhandler。ChannelInboundHandlerAdapter的channelRead方法處理完消息後不會自動釋放消息,若想自動釋放收到的消息,可以使用SimpleChannelInboundHandler<I>.使用ChannelInboundHandler、ChannelInboundHandlerAdapter、SimpleChannelInboundhandler這三個中的一個來處理接收消息,使用哪一個取決于需求;大多數時候使用SimpleChannelInboundHandler處理消息,使用ChannelInboundHandlerAdapter處理其他的“入站”事件或狀态改變。

        ChannelInitializer用來初始化ChannelHandler,将自定義的各種ChannelHandler添加到ChannelPipeline中。

ChannelOutboundHandler類的用法

       它用來處理出站資料(寫資料),它提供了以下幾種方法:            1.bind方法:channel綁定本地方法。            2.connect方法:Channel連接配接操作。            3.disconnect方法:Channel斷開連接配接。            4.close方法:關閉Channel。            5.deregister方法:登出Channel方法            6.read方法:讀取方法,實際是截獲ChannelHandlerContext.read            7.write方法:寫操作,實際是通過ChannelPipeline寫消息,Channel.flush方法重新整理到實際通道中            8.flush方法:重新整理消息到通道。        它是ChannelHandler的子類,實作了父類的所有方法。一旦請求停止從ChannelPipeline轉發參數,則必須得到通知,是因為它所有重要的方法才去ChannelPromise機制。netty提供了它的實作類,ChannelOutboundHanlderAdapter類。              重要的是要記得釋放緻遠并通知 ChannelPromise ,若 ChannelPromise 沒有被通知可能會導緻其中一個 ChannelFutureListener 不被通知去處理一個消息。