Netty入门(五)ChanneHandler
本节主要讨论了 Netty 的数据处理组件 ChannelHandler。
一、Channel 生命周期
Channel 有个简单但强大的状态模型,下面是 Channel 的四个状态:

Channel 的正常生命周期如下图,当这些状态发生变化时,对应的事件将会生成。

二、ChannelHandler 生命周期
ChannelHandler 定义的生命周期如下,当 ChannelHandler 添加到 ChannelPipeline,或者从 ChannelPipeline 移除后,这些将会调用。

三、ChannelInbounderHandler
ChannelInboundHandler 的生命周期方法如下,当接收到数据或者与之关联的 Channel 状态改变时调用。

可以看到,这些方法与 Channel 的生命周期接近。
其中 channelRead 和 channelReadComplete 方法在读操作开始和完成时调用。
另外,channelWritabilityChanged 方法在 channel 写状态发生变化时调用。
四、ChannelOutboundHandler
ChannelOutboundHandler 提供了出站操作时调用的方法。
另外,它具有在请求时演示操作或者事件的能力。比如,当你在写数据到远程的过程中被意外暂停,你可以延时进行刷新操作,然后在迟些时候继续。
下面是提供的方法(继承自 ChannelHandler 未列出来):

五、资源管理
Netty 使用引用计数器来处理池化的 ByteBuf。所以当 ByteBuf 完全处理后,要确保引用计数器被调整。
当你覆盖了 channelRead 操作,在处理完消息之后,需要释放它,如下:
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
/**
* 收到数据时调用
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 丢弃收到的数据
((ByteBuf) msg).release();
}
}
Netty 提供了一个特殊的称为 SimpleChannelInboundHander 的实现,该实现将在用户通过 channelRead0() 方法处理完数据之后,自动释放该消息。
当你在处理写操作,并丢弃消息时,你需要通知 ChannelPromise 数据已经被处理,如下:
public class DiscardOutbounderHandler extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx,
Object msg, ChannelPromise promise) throws Exception {
ReferenceCountUtil.release(msg); // 释放资源
promise.setSuccess(); // 通知 ChannelPromise 数据已经被处理
}
}
六、使用 ChannelHandler
下图展示了 ChannelPipeline,Channel,ChannelHandler 和 ChanelHandlerContext 的关系:

- Channel 绑定到 ChannelPipeline
- ChannelPipeline 绑定到包含 ChannelHandler 的 Channel
- ChannelHandler
- 当添加 ChannelHandler 到 ChannelPipeline 时,ChannelHandlerContext 被创建
如果要完成一个写操作,有以下两种方式:
第一种就是从 ChannelHandlerContext 获取到 Channel 的引用,执行 Channel 上的 write() 方法,如下:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 丢弃收到的数据
((ByteBuf) msg).release();
Channel channel = ctx.channel(); // 获取channel引用
// 通过channel写缓存
channel.write(Unpooled.copiedBuffer("Netty", CharsetUtil.UTF_8));
}
第二种是从 ChannelHandlerContext 获取到 ChannelPipeline 的引用,执行 ChannelPipeline 上的 write() 方法,如下:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ChannelPipeline pipeline = ctx.pipeline(); // 获取pipeline引用
// 通过pipeline写缓存
pipeline.write(Unpooled.copiedBuffer("Netty", CharsetUtil.UTF_8));
}
写操作流程如下:

- 事件传递给 ChannelPipeline 的第一个 ChannelHandler
- ChannelHandler 通过关联的 ChannelHandlerContext 传递事件给 ChannelPipeline 中的下一个 ChannelHandler
- 与 2 类似
但是有些时候不希望总是从 ChannelPipeline 的第一个 ChannelHandler 开始事件,我们希望从一个特定的 ChannelHandler 开始处理。你必须引用于此 ChannelHandler 的前一个 ChannelHandler 关联的 ChannelHandlerContext,利用它调用与自身关联的 ChannelHandler 的下一个 ChannelHandler。如下:
ChannelHandlerContext ctx = context; // 获得 ChannelHandlerContext引用
// write()将会把缓冲区发送到下一个ChannelHandler
ctx.write(Unpooled.copiedBuffer("Netty in Action", CharsetUtil.UTF_8));
流程如下:

- 直接从特定的 ChannelHandler 开始执行
- 事件发送到下一个 ChannelHandler
- 经过最后一个 ChannelHandler 后,事件从 ChannelPipeline 移除
Netty入门(五)ChanneHandler的更多相关文章
- Netty入门
一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...
- Netty入门教程——认识Netty
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...
- Netty入门与实战教程总结分享
前言:都说Netty是Java程序员必须要掌握的一项技能,带着不止要知其然还要知其所以然的目的,在慕课上找了一个学习Netty源码的教程,看了几章后着实有点懵逼.虽然用过Netty,并且在自己的个人网 ...
- openresty 前端开发入门五之Mysql篇
openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...
- Netty(五)序列化protobuf在netty中的使用
protobuf是google序列化的工具,主要是把数据序列化成二进制的数据来传输用的.它主要优点如下: 1.性能好,效率高: 2.跨语言(java自带的序列化,不能跨语言) protobuf参考文档 ...
- Thinkphp入门 五 —模型 (49)
原文:Thinkphp入门 五 -模型 (49) [数据库操作model模型] model 模型 数据库操作 tp框架主要设计模式:MVC C:controller 控制器 shop/Li ...
- DevExpress XtraReports 入门五 创建交叉表报表
原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...
- Netty入门之客户端与服务端通信(二)
Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
- Netty入门之HelloWorld
Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...
- 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?
本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言 老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...
随机推荐
- 2017.12.21-JQuery
作业:密码加强验证 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> & ...
- jsp、css中引入外部资源相对路径的问题
在jsp页面中添加base,可用相对路径: <% String path = request.getContextPath(); String basePath = request.getSch ...
- AutoMapper在项目中的应用
一.先说说DTO DTO是个什么东东? DTO(Data Transfer Object)就是数据传输对象,说白了就是一个对象,只不过里边全是数据而已. 为什么要用DTO? 1.DTO更注重数据,对领 ...
- Velocity快速入门
Velocity 介绍 Velocity是一个基于java的模板引擎.它允许任何人使用简单但功能强大的模板语言引用Java代码中定义的对象. 当Velocity用于web开发时,web设计人员可以与J ...
- 登录PeopleTools 提示ora-00942表视图不存在 select xxx from sysadm.psoprdefn
起因:本来跟DBA说了把生产的库同步到CFG环境,还跟她说了,dev tst cfg在一台机器上,结果她还是把dev给覆盖了,幸好及时发现,一部分对象被删除了(序列,视图,有可能也有表). 视图和一部 ...
- SD从零开始05-06
SD从零开始5 从库存销售 销售凭证类型Sales document type: 用来鉴别和控制不同的业务流程类型: 标准的销售凭证类型: standard order: Rush order: Ca ...
- css 常用的几种垂直居中(包括图片)
我知道现在有非常多的水平垂直居中的写法,我就写一些我自己常用的方法,同时说明一下优缺点 <div class="wrapper"> <div class=&quo ...
- Fiddler抓包使用教程-会话图标
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72933882 本文出自[赵彦军的博客] 使用fiddler抓包时,会看到左侧按照顺 ...
- MySQL——优化ORDER BY语句
本篇文章我们将了解ORDER BY语句的优化,在此之前,你需要对索引有基本的了解,不了解的朋友们可以先看一下我之前写过的索引相关文章.现在让我们开始吧. MySQL中的两种排序方式 1.通过有序索引顺 ...
- CSS 小结笔记之BFC
BFC 即为Block formatting context 的缩写,BFC 主要用来将一个盒子设置为一个隔离的容器,不管盒子内部的元素具有什么属性,都不会影响到盒子的外面. 1.哪些元素能产生BFC ...