我们假设现在的Pipeline中的Handler执行器链是这样的:
Pipeline->h1->h2->h3->h4->h5->h6->tail
假设h1,h2,h3是ChannelInboudHadnler入栈处理器,h4,h5,h6是ChannelOutboundHandler出栈处理器
那么Handler的执行顺序是h1->h2->h3->h6->h5->h4,先执行InboundHandler,再反从tail往前找执行OutboundHandler
请阅读下面代码,并尝试理解
public static void main(String[] args) {
//serverBootstrap,就是服务端启动器,启动服务端,并且绑定组件
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
//设置NIOEventLoopGroup包含一组NIOEventLoop,NIOEventLoop其实就是一个单线程(维护Selector,处理channel的请求)
//这里我们设置两个NIOEventLoopGroup,一个充当Boss专门处理连接请求,一个充当Woker专门处理IO读写请求
.group(new NioEventLoopGroup(),new NioEventLoopGroup())
//设置通道类型服务端就是NioServerSocketChannel,客户端是NioSocketChannel
.channel(NioServerSocketChannel.class)
//这里设置的就是Woker(child)的处理器,也就是IO读写的具体实现
.childHandler(new ChannelInitializer<NioSocketChannel>() {
//初始化处理器,处理器用于IO处理的具体实现,把多个处理器加入到pipeline中形成一条处理器连,线程会一次执行这些处理器来完成指定的IO操作
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
ChannelPipeline pipeline = nioSocketChannel.pipeline();
pipeline.addLast(new ChannelInboundHandlerAdapter() {//自定义入栈处理器1
//当收到数据的时候会触发这个方法
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandler-1");
//传给pipline连中的下一个InboundHandler,如果不调用的话就会在这里中断
super.channelRead(ctx,msg);
}
});
pipeline.addLast(new ChannelInboundHandlerAdapter(){//自定义入栈处理器2
//当收到数据的时候会触发这个方法
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandler-2");
//传给pipline连中的下一个InboundHandler,如果不调用的话就会在这里中断
super.channelRead(ctx,msg);
}
});
pipeline.addLast(new ChannelInboundHandlerAdapter(){//自定义入栈处理器3
//当收到数据的时候会触发这个方法
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandler-3");
ctx.channel().writeAndFlush("hello");
}
});
pipeline.addLast(new ChannelOutboundHandlerAdapter(){//自定义出战处理器1
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandler-1");
}
});
pipeline.addLast(new ChannelOutboundHandlerAdapter(){//自定义出战处理器2
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandler-2");
//调用super.write(ctx, msg, promise),传给下一个OutboundHandler
super.write(ctx, msg, promise);
}
});
pipeline.addLast(new ChannelOutboundHandlerAdapter(){//自定义出战处理器3
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandler-3");
//调用super.write(ctx, msg, promise),传给下一个OutboundHandler
super.write(ctx, msg, promise);
}
});
}
})
.bind(8080);//绑定服务器的监听端口
}
执行顺序结果
那么InboudHandler和OutboundHandler是如何做到把任务交给下一个对应的InboundHandler和OutboundHandler处理的呢?
这里ChannelRead()方法中调用了super.channelRead(ctx,msg)
,交给下一个InboundHandler中的channelRead()处理
System.out.println("InboundHandler-2");
//传给pipline连中的下一个InboundHandler,如果不调用的话就会在这里中断
super.channelRead(ctx,msg);
同理Write()也是调用super.write(ctx, msg, promise);
,交给下一个OutboundHandler中的Write()方法来处理
pipeline.addLast(new ChannelOutboundHandlerAdapter(){//自定义出战处理器2
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandler-2");
//调用super.write(ctx, msg, promise),传给下一个OutboundHandler
super.write(ctx, msg, promise);
}
});