介绍我们在介绍channel的时候提到过,channel中几乎所有的实现都是通过channelPipeline进行的。作为管道,它是如何工作的?一起来看看吧。ChannelPipelineChannelPipeline是一个接口,它继承了三个接口,分别是ChannelInboundInvoker、ChannelOutboundInvoker和Iterable:publicinterfaceChannelPipelineextendsChannelInboundInvoker,ChannelOutboundInvoker,Iterable>继承自ChannelInboundInvoker,表示ChannelPipeline可以在nnelchannelbo中触发的一些事件,例如:ChannelInboundInvokerfireChannelRegistered();ChannelInboundInvokerfireChannelUnregistered();ChannelInboundInvokerfireChannelActive();ChannelInboundInvokerfireChannelInactive();ChannelInboundInvokerfireExceptionCaught(Throwablecause);ChannelInboundInvokerfireUserEventTriggered(Objectevent);ChannelInboundInvokerfireChannelRead(Objectmsg);ChannelInboundInvokerfireChannelReadComplete();ChannelInboundInvokerfireChannelWritabilityChanged();继承自ChannelOutboundInvoker,表示ChannelPipeline可以对通道进行一些主动操作,例如:bind、connect、disconnect、close、deregister、read、write、flush等操作。继承自Iterable,也就是说ChannelPipeline是可遍历的。为什么ChannelPipeline是可遍历的?因为ChannelPipeline中可以加入一个或多个ChannelHandlers,所以ChannelPipeline可以看作是ChannelHandlers的集合。例如ChannelPipeline提供了一系列的添加ChannelHandler的方法:ChannelPipelineaddFirst(Stringname,ChannelHandlerhandler);ChannelPipelineaddFirst(EventExecutorGroupgroup,Stringname,ChannelHandlerhandler);ChannelPipelineaddFirst(EventExecutorGroupgroup,ChannelHandler...handlersline);ChannelFirstPi(ChannelHandler...handlers);ChannelPipelineaddLast(Stringname,ChannelHandlerhandler);ChannelPipelineaddLast(EventExecutorGroupgroup,Stringname,ChannelHandlerhandler);ChannelPipelineaddLast(ChannelHandler...handlers);ChannelPipelineaddLast(EventExecutorGroupgroup,ChannelHandler...handlers);ChannelPipelineaddBefore(StringbaseName,Stringname,ChannelHandlerhandler);ChannelPipelineaddBefore(EventExecutorGroupgroup,StringbaseName,Stringname,ChannelHandlerhandler);ChannelPipelineaddAfter(StringbaseName,Stringname,ChannelHandlerhandler);ChannelPipelineaddAfter(EventExecutorGroup组、StringbaseName、Stringname、ChannelHandler处理程序);可以从前面添加,也可以从后面添加,也可以从特定位置添加。另外,可以从pipeline中删除特定的channelHandler,或者可以移除并替换特定的locationhandler:(ChannelHandleroldHandler,StringnewName,ChannelHandlernewHandler);ChannelHandlerreplace(StringoldName,StringnewName,ChannelHandlernewHandler);:ChannelHandlerfirst();ChannelHandlerlast();ChannelHandlerget(Stringname);Listnames();也可以根据传入的ChannelHandler获取handler对应的ChannelHandlerContext。ChannelHandlerContextcontext(ChannelHandlerhandler);ChannelPipeline中还有一些触发channel相关的事件,如:ChannelPipelinefireChannelRegistered();ChannelPipelinefireChannelUnregistered();ChannelPipelinefireChannelActive();ChannelPipelinefireChannelInactive();ChannelPipelinefireExceptionCaught(Throwable原因);ChannelPipelinefireUserEventTriggered(对象事件);ChannelPipelinefireChannelRead(Objectmsg);ChannelPipelinefireChannelReadComplete();ChannelPipelinefireChannelWritabilityChanged();事件传递有些朋友可能会问,既然ChannelPipeline包含了很多handler,那么handler中的事件是如何传递的呢??其实这些事件都是通过调用ChannelHandlerContext中相应的方法来触发的。对于Inbound事件来说,可以调用下面的方法,进行事件的传递:ChannelHandlerContext.fireChannelRegistered()ChannelHandlerContext.fireChannelActive()ChannelHandlerContext.fireChannelRead(Object)ChannelHandlerContext.fireChannelReadComplete()ChannelHandlerContext.fireExceptionCaught(Throwable)ChannelHandlerContext.fireUserEventTriggered(Object)ChannelHandlerContext.fireChannelWritabilityChanged()ChannelHandlerContext.fireChannelInactive()ChannelHandlerContext.fireChannelUnregistered()对于Outbound事件来说,可以调用下面的方法,进行事件的传递:ChannelHandlerContext.bind(SocketAddress,ChannelPromise)ChannelHandlerContext.connect(SocketAddress,SocketAddress,ChannelPromise)ChannelHandlerContext.write(Object,ChannelPromise)ChannelHandlerContext.flush()ChannelHandlerContext.read()ChannelHandlerContext.disconnect(ChannelPromise)ChannelHandlerContext.close(ChannelPromise)ChannelHandlerContext.deregister(ChannelPromise)ThecorrespondingmethodinthehandlerChannel:publicclassMyInboundHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelActive(ChannelHandlerContextctx){System.out.println("已连接!");ctx.fireChannelActive();{System.out.println("正在关闭..");ctx.close(承诺);DefaultChannelPipelineChannelPipeline官方有一个实现叫DefaultChannelPipeline,因为对于pipeline来说,主要的作用就是管理handler和传递事件。相对来说功能比较简单,但是也有一些特殊的实现地方。例如,它有两个AbstractChannelHandlerContext类型的head和tail。我们知道ChannelPipeline其实是很多handler的集合,那么这些集合是怎么存储的呢?这个存储的数据结构是AbstractChannelHandlerContext。每个AbstractChannelHandlerContext都有一个next节点和一个prev节点,形成一个双向链表。同样在DefaultChannelPipeline中使用head和tail来存储封装的处理程序。注意,虽然这里的head和tail都是AbstractChannelHandlerContext,但是两者还是略有不同的。先看head和tail的定义:protectedDefaultChannelPipeline(Channelchannel){this.channel=ObjectUtil.checkNotNull(channel,"channel");succeededFuture=newSucceededChannelFuture(channel,null);voidPromise=newVoidChannelPromise(channel,true);tail=newTailContext(这个);head=newHeadContext(this);head.next=尾巴;tail.prev=head;}在DefaultChannelPipeline的构造函数中,初始化tail和head,其中tail为TailContext,head为HeadContext。其中TailContext实现了ChannelInboundHandler接口:finalclassTailContextextendsAbstractChannelHandlerContextimplementsChannelInboundHandler而HeadContext实现了ChannelOutboundHandler和ChannelInboundHandler接口:finalclassHeadContextextendsAbstractChannelHandlerContextimplementsChannelOutboundHandler,ChannelInboundHandler下面我们以addFirst方法为例,来看一下handler是怎么被加入pipline的:publicfinalChannelPipelineaddFirst(EventExecutorGroupgroup,Stringname,ChannelHandlerhandler){finalAbstractChannelHandlerContextnewCtx;synchronized(this){checkMultiplicity(handler);name=filterName(name,handler);newCtx=newContext(grouper,name)addFirst0(newCtx);//IftheregisteredisfalseitmeansthatthechannelwasnotregisteredonaneventLoopyet.//Inthiscaseweaddthecontexttothepipelineandaddataskthatwillcall//ChannelHandler.handler注册频道后添加(...)。如果(!registered){newCtx.setAddPending();callHandlerCallbackLater(newCtx,true);归还这个;}EventExecutor执行器=newCtx.executor();如果(!executor.inEventLoop()){callHandlerAddedInEventLoop(newCtx,executor);归还这个;}}callHandlerAdded0(newCtx);归还这个;其工作逻辑是先根据传入的handler构造一个新的context,然后调用addFirst0方法将context添加到AbstractChannelHandlerContext组成的双向链表中:;newCtx.prev=头;newCtx.next=nextCtx;方法来触发上下文的handlerAdded方法综上所述,channelPipeline负责管理channel的各种handler。在DefaultChannelPipeline中,AbstractChannelHandlerContext的head和tail用于存储多个handler。同时,使用这种链式结构来管理各种处理程序也非常方便。本文已收录于http://www.flydean.com/04-3-netty-channelpipeline/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等着你等你发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!