03Handler

Handler

常见Handler

1.粘包半包的那些Handler

2.LoggingHandler

当添加.addLast("logging", new LoggingHandler(LogLevel.INFO))这行代码时

Netty就会以给定的日志级别打印出LoggingHandler中的日志。

可以对入站\出站事件进行日志记录,从而方便我们进行问题排查。

假如现在添加这行代码访问http://127.0.0.1:8007/Action?name=1234510

1
2
3
4
5
6
7
19:10:52.089 [nioEventLoopGroup-2-6] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4a9db561, L:/127.0.0.1:8007 - R:/127.0.0.1:53151] REGISTERED
19:10:52.089 [nioEventLoopGroup-2-6] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4a9db561, L:/127.0.0.1:8007 - R:/127.0.0.1:53151] ACTIVE
19:10:52.090 [nioEventLoopGroup-2-6] DEBUG com.bihang.seaya.server.handler.SeayaHandler - io.netty.handler.codec.http.DefaultHttpRequest
19:10:52.090 [nioEventLoopGroup-2-6] DEBUG com.bihang.seaya.server.handler.SeayaHandler - uri/Action?name=1234510
19:10:52.090 [nioEventLoopGroup-2-6] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4a9db561, L:/127.0.0.1:8007 - R:/127.0.0.1:53151] CLOSE
19:10:52.090 [nioEventLoopGroup-2-6] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4a9db561, L:/127.0.0.1:8007 ! R:/127.0.0.1:53151] INACTIVE
19:10:52.090 [nioEventLoopGroup-2-6] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4a9db561, L:/127.0.0.1:8007 ! R:/127.0.0.1:53151] UNREGISTERED

如果没有这行代码的打印信息

1
2
19:15:02.292 [nioEventLoopGroup-2-2] DEBUG com.bihang.seaya.server.handler.SeayaHandler - io.netty.handler.codec.http.DefaultHttpRequest
19:15:02.292 [nioEventLoopGroup-2-2] DEBUG com.bihang.seaya.server.handler.SeayaHandler - uri/Action?name=1234510

3.IdleStatHandler

检测空闲时间的Handler

如果超过读空闲时间 会触发IdleStat#READER_IDLE事件

如果超过写空闲时间 会触发IdleStat#READ_IDLE事件

如果超过读写空闲时间 会触发IdleStat#ALL_IDLE事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//第一个参数 读空闲时间 seconds
//第二个参数 写空闲时间 seconds
//第三个参数 读写空闲时间 seconds
pipeline.addLast(new IdleStateHandler(5,5,5));
pipeline.addLast(new ChannelDuplexHandler(){
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleState evt1 = (IdleState) evt;

if(evt1.equals(IdleState.READER_IDLE)){
//todo
}else{
//todo...
}
}
});

4.ByteToMessageCodec

ByteBuf和自定义Message的编解码器

不能是@Shareable

不用自己管理Bytebuf

5.MessageToMessageCodec

不同Message之间的编解码器

可以使@Shareable

不用自己管理ByteBuf

6.SimpleChannelInboundHandler

处理某种特定消息(泛型)的入栈处理器

可以使用@Shareable

@Shareable

标注一个channel handler可以被多个channel安全地共享。

ChannelHandlerAdapter还提供了实用方法isSharable()。如果其对应的实现被标注为Sharable,那么这个方法将返回true,表示它可以被添加到多个ChannelPipeline中。

因为一个ChannelHandler可以从属于多个ChannelPipeline,所以它也可以绑定到多个ChannelHandlerContext实例。用于这种用法的ChannelHandler必须要使用@Sharable注解标注;否则,试图将它添加到多个ChannelPipeline时将会触发异常。显而易见,为了安全地被用于多个并发的Channel(即连接),这样的ChannelHandler必须是线程安全的。

共享的Handler可以在pipeLine.addLast的时候提成公共变量,每个pipeLine中都是一个实例

ChannelOutboundHandler会声明一个read方法

异常处理

入站异常处理:

1、ChannelHandler.exceptionCaught()的默认实现是简单地将当前异常转发给ChannelPipeline 中的下一个 ChannelHandler;
2、如果异常到达了 ChannelPipeline 的尾端,它将会被记录为未被处理;
3、要想定义自定义的处理逻辑,你需要重写 exceptionCaught()方法。一般将这个Channelhandler放在 ChannelPipeline 的最后,确保所有的入站异常都总会被处理。

1
2
3
4
5
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.channel().close();
}

出站异常处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public void channelActive(ChannelHandlerContext ctx) {
ChannelFuture channelFuture = ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rock!", CharsetUtil.UTF_8));
//出站异常处理
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
future.cause().printStackTrace();
future.channel().close();
}
}
});
}

03Handler
https://jiajun.xyz/2022/05/26/java/netty/v2/03Handler/
作者
Lambda
发布于
2022年5月26日
许可协议