«1. Обзор
В этой быстрой статье мы рассмотрим обработку исключений в Netty.
Проще говоря, Netty — это платформа для создания высокопроизводительных асинхронных и управляемых событиями сетевых приложений. Операции ввода-вывода обрабатываются внутри его жизненного цикла с использованием методов обратного вызова.
Более подробную информацию о фреймворке и о том, как начать работу с ним, можно найти в нашей предыдущей статье здесь.
2. Обработка исключений в Netty
Как упоминалось ранее, Netty является системой, управляемой событиями, и имеет методы обратного вызова для определенных событий. Исключениями являются и такие события.
Исключения могут возникать при обработке данных, полученных от клиента, или во время операций ввода-вывода. Когда это происходит, запускается специальное событие исключения.
2.1. Обработка исключений в канале происхождения
Событие, перехваченное исключением, при запуске обрабатывается методом exceptionsCaught() объекта ChannelInboundHandler или его адаптеров и подклассов.
Обратите внимание, что обратный вызов устарел в интерфейсе ChannelHandler. Теперь он ограничен интерфейсом ChannelInboudHandler.
Метод принимает в качестве параметров объект Throwable и объект ChannelHandlerContext. Объект Throwable можно использовать для печати трассировки стека или получения локализованного сообщения об ошибке.
Итак, давайте создадим обработчик канала ChannelHandlerA и переопределим его exceptionCaught() с помощью нашей реализации:
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.info(cause.getLocalizedMessage());
//do more exception handling
ctx.close();
}
В приведенном выше фрагменте кода мы записали сообщение об исключении, а также вызвали close() ChannelHandlerContext.
Это закроет канал между сервером и клиентом. По сути, заставляя клиента отключиться и завершить работу.
2.2. Распространение исключений
В предыдущем разделе мы обработали исключение в его исходном канале. Однако на самом деле мы можем передать исключение другому обработчику канала в конвейере.
Вместо регистрации сообщения об ошибке и вызова ctx.close() мы будем использовать объект ChannelHandlerContext для ручного запуска другого события, перехваченного исключением.
Это приведет к вызову exceptionCaught() следующего обработчика канала в конвейере.
Давайте изменим фрагмент кода в ChannelHandlerA, чтобы событие распространялось вызовом ctx.fireExceptionCaught():
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.info("Exception Occurred in ChannelHandler A");
ctx.fireExceptionCaught(cause);
}
Кроме того, давайте создадим еще один обработчик канала, ChannelHandlerB, и переопределим его exceptionCaught() с помощью этой реализации: ~~ ~
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.info("Exception Handled in ChannelHandler B");
logger.info(cause.getLocalizedMessage());
//do more exception handling
ctx.close();
}
В классе Server каналы добавляются в конвейер в следующем порядке:
ch.pipeline().addLast(new ChannelHandlerA(), new ChannelHandlerB());
Распространение событий, перехваченных исключениями, вручную полезно в тех случаях, когда все исключения обрабатываются одним назначенным обработчиком канала.
3. Заключение
В этом руководстве мы рассмотрели, как обрабатывать исключения в Netty с помощью метода обратного вызова и как при необходимости распространять исключения.
Полный исходный код доступен на Github.