JDK 提供了 ObjectOutputStream 和 ObjectInputStream 通過網絡將原始數據類型和 POJO 進行序列化和反序列化。API并不復雜,可以應用到任何對象,支持 java.io.Serializable 接口。但它也不是非常高效的。在本節中,我們將看到 Netty 所提供的。
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Serializing%20data.md#jdk-序列化)JDK 序列化
如果程序與端對端間的交互是使用 ObjectOutputStream 和 ObjectInputStream,并且主要面臨的問題是兼容性,那么,[JDK 序列化](http://docs.oracle.com/javase/7/docs/technotes/guides/serialization/)?是不錯的選擇。
表8.8列出了序列化類,Netty 提供了與 JDK 的互操作。
Table 8.8 JDK Serialization codecs
| 名稱 | 描述 |
| --- | --- |
| CompatibleObjectDecoder | 該解碼器使用 JDK 序列化,用于與非 Netty 進行互操作。 |
| CompatibleObjectEncoder | 該編碼器使用 JDK 序列化,用于與非 Netty 進行互操作。 |
| ObjectDecoder | 基于 JDK 序列化來使用自定義序列化解碼。外部依賴被排除在外時,提供了一個速度提升。否則選擇其他序列化實現 |
| ObjectEncoder | 基于 JDK 序列化來使用自定義序列化編碼。外部依賴被排除在外時,提供了一個速度提升。否則選擇其他序列化實現 |
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Serializing%20data.md#jboss-marshalling-序列化)JBoss Marshalling 序列化
如果可以使用外部依賴 JBoss Marshalling 是個明智的選擇。比 JDK 序列化快3倍且更加簡練。
*[JBoss Marshalling](https://www.jboss.org/jbossmarshalling)?是另一個序列化 API,修復的許多 JDK序列化 API 中發現的問題,它與 java.io.Serializable 完全兼容。并添加了一些新的可調參數和附加功能,所有這些都可插入通過工廠配置外部化,類/實例查找表,類決議,對象替換,等等)*
下表展示了 Netty 支持 JBoss Marshalling 的編解碼器。
Table 8.9 JBoss Marshalling codecs
| 名稱 | 描述 |
| --- | --- |
| CompatibleMarshallingDecoder | 為了與使用 JDK 序列化的端對端間兼容。 |
| CompatibleMarshallingEncoder | 為了與使用 JDK 序列化的端對端間兼容。 |
| MarshallingDecoder | 使用自定義序列化用于解碼,必須使用 |
MarshallingEncoder MarshallingEncoder | 使用自定義序列化用于編碼,必須使用 MarshallingDecoder
下面展示了使用 MarshallingDecoder 和 MarshallingEncoder
Listing 8.13 Using JBoss Marshalling
~~~
public class MarshallingInitializer extends ChannelInitializer<Channel> {
private final MarshallerProvider marshallerProvider;
private final UnmarshallerProvider unmarshallerProvider;
public MarshallingInitializer(UnmarshallerProvider unmarshallerProvider,
MarshallerProvider marshallerProvider) {
this.marshallerProvider = marshallerProvider;
this.unmarshallerProvider = unmarshallerProvider;
}
@Override
protected void initChannel(Channel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new MarshallingDecoder(unmarshallerProvider));
pipeline.addLast(new MarshallingEncoder(marshallerProvider));
pipeline.addLast(new ObjectHandler());
}
public static final class ObjectHandler extends SimpleChannelInboundHandler<Serializable> {
@Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, Serializable serializable) throws Exception {
// Do something
}
}
}
~~~
### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Serializing%20data.md#protobuf-序列化)ProtoBuf 序列化
ProtoBuf 來自谷歌,并且開源了。它使編解碼數據更加緊湊和高效。它已經綁定各種編程語言,使它適合跨語言項目。
下表展示了 Netty 支持 ProtoBuf 的 ChannelHandler 實現。
Table 8.10 ProtoBuf codec
| 名稱 | 描述 |
| --- | --- |
| ProtobufDecoder | 使用 ProtoBuf 來解碼消息 |
| ProtobufEncoder | 使用 ProtoBuf 來編碼消息 |
| ProtobufVarint32FrameDecoder | 在消息的整型長度域中,通過 "[Base 128 Varints](https://developers.google.com/protocol-buffers/docs/encoding)"將接收到的 ByteBuf 動態的分割 |
用法見下面
Listing 8.14 Using Google Protobuf
~~~
public class ProtoBufInitializer extends ChannelInitializer<Channel> {
private final MessageLite lite;
public ProtoBufInitializer(MessageLite lite) {
this.lite = lite;
}
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new ProtobufDecoder(lite));
pipeline.addLast(new ObjectHandler());
}
public static final class ObjectHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
// Do something with the object
}
}
}
~~~
1. 添加 ProtobufVarint32FrameDecoder 用來分割幀
2. 添加 ProtobufEncoder 用來處理消息的編碼
3. 添加 ProtobufDecoder 用來處理消息的解碼
4. 添加 ObjectHandler 用來處理解碼了的消息
本章在這最后一節中,我們探討了 Netty 支持的不同的序列化的專門的解碼器和編碼器。這些是標準 JDK 序列化 API,JBoss Marshalling 和谷歌ProtoBuf。
- 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