如何捕获netty中的所有异常

Ale*_*xis 13 java exception-handling netty

据我所知,netty通过覆盖方法exceptionCaught()来处理异常.但我想要的是一个可以处理所有异常的处理程序.所以,管道应该是这样的:

InboundExceptionHandler - inboundHandler1 - inboundHandler2 - outboundHandler1 - outboundHandler2 - OutboundExceptionHandler

这意味着我应该在头部和尾部分开的管道中放置2个异常处理程序.但我觉得它看起来很难看.任何更好的主意?

Ben*_*ans 21

您可以在管道的顶部/尾部只有一个入站和出站异常处理程序.如果你想捕获所有异常,你可以做这样的事情(我假设这是Netty 4.0):

import io.netty.channel.*;

import java.net.SocketAddress;

public class ExceptionHandler extends ChannelDuplexHandler {

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Uncaught exceptions from inbound handlers will propagate up to this handler 
    }

    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                if (!future.isSuccess()) {
                    // Handle connect exception here...
                }
            }
        }));
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        ctx.write(msg, promise.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                if (!future.isSuccess()) {
                    // Handle write exception here...
                }
            }
        }));
    }

    // ... override more outbound methods to handle their exceptions as well
}
Run Code Online (Sandbox Code Playgroud)

入站处理程序抛出的任何异常都将向上传播管道并调用此处理程序的exceptionCaught()方法,假设下面的处理程序不使用它们.

对于像write()和的出站操作connect(),您需要添加一个ChannelFutureListener来捕获它们的异常.该exceptionCaught()方法只调用从像入站事件例外channelRead(),channelActive()等等.

使用此处理程序位于管道的"顶部",我们可以从下面的所有出站处理程序中捕获异常.假设你的一个出站处理程序正在进行一些编码,这会因异常而失败,这将由我们添加到write()操作的promise中的通道未来侦听器处理.

如果这个异常处理程序像你最初建议的那样安装在管道的"底部"/头部,那么就不会看到它上面的处理程序的异常,因为write()如果在前一个处理程序中写入失败,它的方法永远不会被调用.这就是为什么这个处理程序必须位于顶部.

为了避免混淆管道的顶部/底部,我将如何配置您的示例管道:

pipeline.addLast(outboundHandler2)        // bottom
        .addLast(outboundHandler1)
        .addLast(inboundHandler2)
        .addLast(inboundHandler1)
        .addLast(new ExceptionHandler()); // top
Run Code Online (Sandbox Code Playgroud)