ChannelHandler
类层次关系图
入站和出站:
从服务端的角度,数据从客户端发送到服务端,称之为入站,当数据处理完成返回给客户端,称之为出站。是相对的概念。
从客户端的角度,数据从服务端发送给客户端,称之为入站,当数据返回给服务端,称之为出站。
不论是入站还是出站,handler从一端开始,到另一端结束,以责任链的模式依次执行。
责任链模式——“击鼓传花”,当请求被不同的接收者处理时,每个接收者都包含对下一个接收者的引用,一个接收者处理完成后,将依次向下传递。
适配器模式——出国时要使用的电源转换器(美国/日本110V 中国220V电压),作为两个不兼容的接口之间的桥梁,将类的接口转换为需要的另外一种接口。
ChannelDuplexHandler是除了入站和出站handler之外的,另一个常用子类。
它同时实现了ChannelInboundHandler和ChannelOutboundHandler接口,如果需要既处理入站事件又处理出站事件,可以继承此类。
serverBootstrap.handler(new LoggingHandler(LogLevel.INFO)) ------------------------------------------------------------------ public class LoggingHandler extends ChannelDuplexHandler{} ------------------------------------------------------------------ public class ChannelDuplexHandler extends ChannelInboundHandlerAdapter implements ChannelOutboundHandler {} ------------------------------------------------------------------ public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {}
ChannelHandlerAdapter
提供了额外的isSharable()方法,用来判断handler是否可以被共享到多个pipeline之中。默认情况不共享,如果需要共享,在继承了适配器的handler上,增加注解@Sharable
@Sharable public class LoggingHandler extends ChannelDuplexHandler {}
ChannelInboundHandler
最重要的方法是channelRead(),在使用时,需要显式 释放ByteBuf相关的内存。使用ReferenceCountUtil是引用计数的工具类。
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // netty中的缓冲区 叫做ByteBuf -- 对ByteBuffer的封装 ByteBuf buf = (ByteBuf) msg; // 释放ByteBuf内存 ReferenceCountUtil.release(msg); }
为了减少对资源内存的管理,使用SimpleChannelInboundHandler,使用其channelRead0()方法,可以自动释放资源,使用更便利。
SimpleChannelInboundHandler源码 ------------------------------------------------ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { boolean release = true; try { if (acceptInboundMessage(msg)) { @SuppressWarnings("unchecked") I imsg = (I) msg; channelRead0(ctx, imsg); } else { release = false; ctx.fireChannelRead(msg); } } finally { if (autoRelease && release) { ReferenceCountUtil.release(msg); } } }