概述
主要介绍四个主要的核心类: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。
如上图,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
修改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中,如下图:
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
不被通知去处理一个消息。