Handler & Pipeline
📢 常用
Handler
使用
ch.pipeline().addLast(new LoggingHandler(LogLevel.*DEBUG*));
//打印日志输出
ch.pipeline().addLast(new StringEncoder());
//把写入的内容转为string
ch.pipeline().addLast(new SimpleChannelInboundHandler<LoginRequestMessage>() {
} //只接收特定消息的handler
ch.pipeline().addLast(
newLengthFieldBasedFrameDecoder(1024,0,0,0,0))
//动态解码器handler
ch.pipeline().addLast(new IdleStateHandler(5,0,0));
//用来判断是不是 读空闲时间过长 或 写空闲时间过长 或者读写空闲时间过长时触发
ch.pipeline().addLast(new ChannelDuplexHandler(){}
//可以同时作为入站和出战处理器// ChannelDuplexHandler 可以同时作为入站或者出战处理器 ch.pipeline().addLast(new ChannelDuplexHandler(){ // 用来触发特殊事件,自定义事件等 @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE){ log.debug("已经五秒没有读到数据了!"); } super.userEventTriggered(ctx, evt); } });
ChannelHandler用来处理Channel上的各种事件,分为入栈,出栈两种。所有ChannelHanndler被连成一串,就是Pipeline
- 入栈处理器通常是ChannelInboundHandlerAdapter的子类,主要用来读取客户端数据,写回结果
- 出栈处理器通常是ChannelOutboundHandlerAdapter的子类,主要对写回结果进行加工
打个比喻,每个Channel是一个产品的加工车间,Pipeline是车间的流水线,ChannelHandler就是流水线上的各道工序,而后面要讲的ByteBuf是原材料,经过很多工序的加工;先经过一道道工序入站工序,再经过一道道出战工序最终变成产品
Pipeline执行顺序
-
h1->h2->h3 入栈顺序是从前往后执行,
-
->h4->h5 出栈顺序是从后面往前执行,先执行h5再执行h4
- 需要执行了writeAndFlush() 关闭方法才会执行出站的Handler
-
super.channelRead(ctx, name) /``ctx.fireChannelRead(msg);
- 两个方法都是用于调用下一个Handler,把值传递过去,下一个Handler的msg就是这个Handler处理过了的参数
- 两者必须调用一个,否则调用链就会断掉
public static void main(String[] args) {
new ServerBootstrap()
.group(new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
// 1、通过channel拿到pipeline
ChannelPipeline pipeline = ch.pipeline();
// 2、添加处理器 head -> h1->h2->h3 ->h4->h5 ->tail
pipeline.addLast("h1",new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.debug("1");
ByteBuf buf = (ByteBuf) msg;
String name = buf.toString(Charset.defaultCharset());
super.channelRead(ctx, name); //调用下一个Handler,把值传递过去,下一个Handler的msg就是这个Handler处理过了的参数
// ctx.fireChannelRead(msg); 或者调用该实现,两则必须调用一个,反正调用链会断
}
});
pipeline.addLast("h2",new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.debug("2");
Student student = new Student((String) msg);
super.channelRead(ctx, student);
}
});
pipeline.addLast("h3",new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.debug("3");
log.debug("对象====》{},{}",msg,msg.getClass());
super.channelRead(ctx, msg);
// 把写入的字符串转为Bytebuffer字节数组
// ch.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
}
});
pipeline.addLast("h4",new ChannelOutboundHandlerAdapter(){
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.debug("出站4");
super.write(ctx, msg, promise);
}
});
pipeline.addLast("h5",new ChannelOutboundHandlerAdapter(){
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.debug("出站5");
super.write(ctx, msg, promise);
}
});
}
}).bind(8080);
}
@Data
@AllArgsConstructor
static class Student{
private String name;
}
Handler测试工具类:EmbeddedChannel
public static void main(String[] args) {
ChannelInboundHandlerAdapter h1 = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.debug("入站1");
super.channelRead(ctx, msg);
}
};
ChannelInboundHandlerAdapter h2 = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.debug("入站2");
super.channelRead(ctx, msg);
}
};
ChannelOutboundHandlerAdapter h4 = new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.debug("出站4");
super.write(ctx, msg, promise);
}
};
ChannelOutboundHandlerAdapter h5 = new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.debug("出站5");
super.write(ctx, msg, promise);
}
};
EmbeddedChannel channel = new EmbeddedChannel(h1, h2, h4,h5);
// 模拟入栈操作
channel.writeInbound(ByteBufAllocator.DEFAULT.buffer().writeBytes("hello".getBytes()));
// 模拟出站操作
channel.writeOutbound(ByteBufAllocator.DEFAULT.buffer().writeBytes("".getBytes()));
}