netty笔记-Pipeline对ChannelHandler的操作

接上篇:netty笔记-Pipeline的事件触发

1. 操作分类

1.1添加操作

  • addFirst
  • addBefore
  • addAfter
  • addLast

1.2移除操作

  • remove

1.3替换操作

replace

2. 测试

2.1 addLast

将Handler添加到尾部前面

        channelInitializer=new ChannelInitializer() { // 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() { // 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() { // 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);
    }

你可能感兴趣的:(netty笔记-Pipeline对ChannelHandler的操作)