Handler在netty中,无疑占据着非常重要的地位。Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码、拦截指定的报文、统一对日志错误进行处理、统一对请求进行计数、控制Handler执行与否。一句话,没有它做不到的只有你想不到的。
Netty中的所有handler都实现自ChannelHandler接口。按照输出输出来分,分为ChannelInboundHandler、ChannelOutboundHandler两大类。ChannelInboundHandler对从客户端发往服务器的报文进行处理,一般用来执行解码、读取客户端数据、进行业务处理等;ChannelOutboundHandler对从服务器发往客户端的报文进行处理,一般用来进行编码、发送报文到客户端。
Netty中,可以注册多个handler。ChannelInboundHandler按照注册的先后顺序执行;ChannelOutboundHandler按照注册的先后顺序逆序执行,如下图所示,按照注册的先后顺序对Handler进行排序,request进入Netty后的执行顺序为:
先举一个例子吧
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
try {
//NIO服务的辅助启动类
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000*60*5)
.handler(new LoggingHandler(LogLevel.DEBUG))//设置父类handler
.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast("idleHandler",new TIdleHandler(AdapterParam.READIDLE, AdapterParam.WRITEIDLE, AdapterParam.ALLIDLE));
//解码器
pipeline.addLast("decoder", new TDecoder());
//编码器
pipeline.addLast("encoder", new TEncoder());
//业务处理器
pipeline.addLast("handler", new THandler());
}
});
b.bind(port).sync();
这里加了四个handler两个outbound handler(idlehander , encoder)和两个inbound handler(decoder , handler) 添加顺序分别为:
idlehandler , decoder , encoder , handler ,
那么inbound的handler执行顺序,也就是收到消息的执行顺序为decoder , handler ,inbound执行顺序为先添加先执行
outbound的handler执行顺序,也就是发送消息的执行顺序为 encoder , idlehandler ,outbound的执行顺序为先添加的后执行
曾经遇到一个问题,在心跳监测中,也就是idlehandler中用ctx发送消息,发现对端接收不到,后来才发现,ctx.writeandflush方法是执行下一个handler,按照这个handler添加顺序,那么久不会执行encoder ,所以消息可能会发送不出去,但是用channel发送消息是重新跑一边所有的outbound handler也就是说会先执行encoder,这样才能将消息发送出去