1. 操作分类
1.1添加操作
- addFirst
- addBefore
- addAfter
- addLast
1.2移除操作
- remove
1.3替换操作
replace
2. 测试
2.1 addLast
将Handler添加到尾部前面
channelInitializer=new ChannelInitializer<SocketChannel>() { // 5、添加一个EchoServer-Handler 到子Channel的ChannelPipeline
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(serverHandler);
ch.pipeline().addLast(new InboundHandlerA());
ch.pipeline().addLast(new InboundHandlerB());
}
};
2.2 addAfter
将Handler添加到某个Handler后面,
baseName表示添加的ChannelHandler名字,name表示要添加的某个ChannelHandler名字
ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
channelInitializer=new ChannelInitializer<SocketChannel>() { // 5、添加一个EchoServer-Handler 到子Channel的ChannelPipeline
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("handler1",serverHandler);
ch.pipeline().addAfter("handler1","handler2",new InboundHandlerA());
ch.pipeline().addAfter("handler1","handler3",new InboundHandlerB());
}
};
其他不再一一列举
3. 多个自定义Handler的事件触发
当多个Handler一起被添加到Pipeline中,需要手动调用Handler的fireChannelRead方法来触发事件.
channelInitializer=new ChannelInitializer<SocketChannel>() { // 5、添加一个EchoServer-Handler 到子Channel的ChannelPipeline
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(serverHandler);
ch.pipeline().addLast(new InboundHandlerA());
ch.pipeline().addLast(new InboundHandlerB());
}
};
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 将消息记录到控制台
ByteBuf in = (ByteBuf) msg;
System.out.println( "Server received: " + in.toString(CharsetUtil.UTF_8));
ctx.fireChannelRead(msg);
}
}
public class InboundHandlerA extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = Unpooled.copiedBuffer("helloA",CharsetUtil.UTF_8);
System.out.println( "helloA");
ctx.fireChannelRead(msg);
}
}
public class InboundHandlerB extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = Unpooled.copiedBuffer("helloB",CharsetUtil.UTF_8);
System.out.println( "helloB");
ctx.fireChannelRead(msg);
}
}
输出结果:
Server received: Netty rocks!
helloA
helloB
4.ByteBuf内存释放问题
在最后一个Handler执行fireChannelRead方法则会执行DefaultChannelPipeline中的tail(ChannelHandlerContext),其会释放ByteBuf内存(调用release方法),所以在中间处理Handler时,对ByteBuf的使用,需要添加remain方法计数,以保持内存的生命的生命周期,如下示例:
- retain引用计数+1
- ctx.write方法则会调用release方法,引用计数-1(需要有promise的情况下)
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ChannelFuture future = ctx.channel().close();
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
System.out.println("x");
}
});
// 将消息记录到控制台
ByteBuf in = (ByteBuf) msg;
System.out.println( "Server received: " + in.toString(CharsetUtil.UTF_8));
// 将接收到的消息写给发送者,而不冲刷出站消息
in.retain();
ctx.write(in);
ctx.fireChannelRead(msg);
}