在所有的例子代碼中,我們在引導過程中通過 handler() 或childHandler() 都只添加了一個 ChannelHandler 實例,對于簡單的程序可能足夠,但是對于復雜的程序則無法滿足需求。例如,某個程序必須支持多個協議,如 HTTP、WebSocket。若在一個 ChannelHandle r中處理這些協議將導致一個龐大而復雜的 ChannelHandler。Netty 通過添加多個 ChannelHandler,從而使每個 ChannelHandler 分工明確,結構清晰。
Netty 的一個優勢是可以在 ChannelPipeline 中堆疊很多ChannelHandler 并且可以最大程度的重用代碼。如何添加多個ChannelHandler 呢?Netty 提供 ChannelInitializer 抽象類用來初始化 ChannelPipeline 中的 ChannelHandler。ChannelInitializer是一個特殊的 ChannelHandler,通道被注冊到 EventLoop 后就會調用ChannelInitializer,并允許將 ChannelHandler 添加到CHannelPipeline;完成初始化通道后,這個特殊的 ChannelHandler 初始化器會從 ChannelPipeline 中自動刪除。
聽起來很復雜,其實很簡單,看下面代碼:
Listing 9.6 Bootstrap and using ChannelInitializer
~~~
ServerBootstrap bootstrap = new ServerBootstrap();//1
bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup()) //2
.channel(NioServerSocketChannel.class) //3
.childHandler(new ChannelInitializerImpl()); //4
ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080)); //5
future.sync();
final class ChannelInitializerImpl extends ChannelInitializer<Channel> { //6
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); //7
pipeline.addLast(new HttpClientCodec());
pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
}
}
~~~
1. 創建一個新的 ServerBootstrap 來創建和綁定新的 Channel
2. 指定 EventLoopGroups 從 ServerChannel 和接收到的管道來注冊并獲取 EventLoops
3. 指定 Channel 類來使用
4. 設置處理器用于處理接收到的管道的 I/O 和數據
5. 通過配置的引導來綁定管道
6. ChannelInitializer 負責設置 ChannelPipeline
7. 實現 initChannel() 來添加需要的處理器到 ChannelPipeline。一旦完成了這方法 ChannelInitializer 將會從 ChannelPipeline 刪除自身。
通過 ChannelInitializer, Netty 允許你添加你程序所需的多個 ChannelHandler 到 ChannelPipeline
- Introduction
- 開始
- Netty-異步和數據驅動
- Netty 介紹
- 構成部分
- 關于本書
- 第一個 Netty 應用
- 設置開發環境
- Netty 客戶端/服務端 總覽
- 寫一個 echo 服務器
- 寫一個 echo 客戶端
- 編譯和運行 Echo 服務器和客戶端
- 總結
- Netty 總覽
- Netty 快速入門
- Channel, Event 和 I/O
- 什么是 Bootstrapping 為什么要用
- ChannelHandler 和 ChannelPipeline
- 近距離觀察 ChannelHandler
- 總結
- 核心功能
- Transport(傳輸)
- 案例研究:Transport 的遷移
- Transport API
- 包含的 Transport
- Transport 使用情況
- 總結
- Buffer(緩沖)
- Buffer API
- ByteBuf - 字節數據的容器
- 字節級別的操作
- ByteBufHolder
- ByteBuf 分配
- 總結
- ChannelHandler 和 ChannelPipeline
- ChannelHandler 家族
- ChannelPipeline
- ChannelHandlerContext
- 總結
- Codec 框架
- 什么是 Codec
- Decoder(解碼器)
- Encoder(編碼器)
- 抽象 Codec(編解碼器)類
- 總結
- 提供了的 ChannelHandler 和 Codec
- 使用 SSL/TLS 加密 Netty 程序
- 構建 Netty HTTP/HTTPS 應用
- 空閑連接以及超時
- 解碼分隔符和基于長度的協議
- 編寫大型數據
- 序列化數據
- 總結
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- 引導
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- NETTY BY EXAMPLE
- 單元測試
- 總覽
- 測試 ChannelHandler
- 測試異常處理
- 總結
- WebSocket
- WebSocket 程序示例
- 添加 WebSocket 支持
- 測試程序
- 總結
- SPDY
- SPDY 背景
- 示例程序
- 實現
- 啟動 SpdyServer 并測試
- 總結
- 通過 UDP 廣播事件
- UDP 基礎
- UDP 廣播
- UDP 示例
- EventLog 的 POJO
- 寫廣播器
- 寫監視器
- 運行 LogEventBroadcaster 和 LogEventMonitor
- 總結
- 高級主題
- 實現自定義的編解碼器
- 編解碼器的范圍
- 實現 Memcached 編解碼器
- 了解 Memcached 二進制協議
- Netty 編碼器和解碼器
- 測試編解碼器
- EventLoop 和線程模型
- 線程模型的總覽
- EventLoop
- EventLoop
- I/O EventLoop/Thread 分配細節
- 總結
- 用例1:Droplr Firebase 和 Urban Airship
- 用例2:Facebook 和 Twitter