Netty - 跳过管道中的其余处理程序

时间:2015-12-17 23:28:13

标签: asynchronous netty

我目前正在使用Netty 4.0,如果这很重要,但无论如何..

我有一个像这样编写的处理程序,我想根据URI过滤掉请求:

public class URIFilterHandler extends SimpleChannelInboundHandler<HttpRequest> {

public void channelRead0(ChannelHandlerContext ctx, HttpRequest req) {
    String uri = req.uri();

    if (uri.contains("abcde")) {
        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NO_CONTENT);
        ctx.writeAndFlush(response);
        // HERE IS WHERE I WANT TO SKIP REST OF THE HANDLERS

    } else {
        ctx.fireChannelRead(req);
    }
}
}

然后这是我的管道

public class ServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    public void initChannel(SocketChannel ch) {
        ChannelPipeline p = ch.pipeline();

        p.addLast(new HttpRequestDecoder());
        p.addLast(new HttpResponseEncoder());
        p.addLast(new URIFilterHandler());
        p.addLast(new HttpObjectAggregator(1048576));
        p.addLast(new RequestHandler());

    }
}

我尝试了以下操作,但它似乎从管道中永久删除了这些处理程序,而不仅仅是针对一个请求。

       ctx.pipeline().remove(HttpObjectAggregator.class);
       ctx.pipeline().remove(RequestHandler.class;)

我尝试使用ctx.channel()。close()和ctx.fireChannelInactive()无济于事。它似乎仍将请求传递给下一个处理程序(在本例中为HttpObjectAggregator)。我认为这可能是由于close()和fireChannelInactive()是异步的?

编辑:看来我遇到的问题是我发回了DefaultHttpResponse。当我发回DefaultFullHttpResponse时,请求永远不会挂起。

2 个答案:

答案 0 :(得分:2)

要跳过剩下的处理程序,就什么都不做。要继续使用下一个处理程序,初始对象或彼此处理数据,请调用ctx.fireChannelRead( object )

照顾引用计数的对象。 SimpleChannelInboundHandler默认释放输入(取决于构造函数参数)。如果您决定将其发送到下一个处理程序,则必须调用ReferenceCountUtil.retain(Object)。 请参阅此处的文档:http://netty.io/wiki/reference-counted-objects.html

此外,我认为您应该将HttpObjectAggregator处理程序放在管道上自己的处理程序之前,并使处理程序捕获FullHttpRequestHttpObjectAggregator为您处理所有http chuncks,并将管道FullHttpRequest放入管道。在你的情况下,它可能是有意思的,因为如果你忽略了一个chunck,你如何处理已经聚合在管道上的其他chuncks?我想如果你什么也不做,你可能会抛出DecoderException。

答案 1 :(得分:0)

如果您未在ctx.fireChannelRead()中呼叫channelRead0,则该消息将不会传播到以下处理程序。这可以通过以下代码片段来演示,其中第一个处理程序过滤掉所有奇数:

    EmbeddedChannel channel = new EmbeddedChannel(
            new SimpleChannelInboundHandler<Integer>() {
                @Override
                protected void channelRead0(ChannelHandlerContext ctx,
                        Integer msg) throws Exception {
                    if (msg % 2 == 0)
                        ctx.fireChannelRead(msg);
                }
            },
            new ChannelInboundHandlerAdapter() {
                @Override
                public void channelRead(ChannelHandlerContext ctx, 
                       Object msg) throws Exception {
                    System.out.println(msg);
                }
            });

    channel.writeInbound(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);