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 .