Netty4.0 開發指導 2

Netty4.0 開發指導 2

原文: http://netty.io/wiki/user-guide-for-4.x.html

聊一下用POJO代替ByteBuf

到目前爲止我們點評的所有代碼實例都使用ByteBuf作爲主要的消息格式. 在這一章節, 我們將改進TIME協議的客戶端和服務端去使用POJO代替ByteBuf.
使用POJO在你的ByteBuf是顯爾易見的; 通過從處理單元中分離從ByteBuf提取信息的代碼你的處理單元更容易維護和重用性更高. 在TIME的實例中, 我們只是讀一個32位整型數字, 這個不是直接使用ByteBuf的主要問題. 然而, 你將發現分離你實現的一個真實的通信協議是很有必要的.
首先, 讓我們定義一個新的類型就叫UnixTime.

01 package io.netty.example.time;
02  
03 import java.util.Date;
04  
05 public class UnixTime {
06  
07     private final int value;
08      
09     public UnixTime() {
10         this((int) (System.currentTimeMillis() / 1000L + 2208988800L));
11     }
12      
13     public UnixTime(int value) {
14         this.value = value;
15     }
16          
17     public int value() {
18         return value;
19     }
20          
21     @Override
22     public String toString() {
23         return new Date((value() - 2208988800L) * 1000L).toString();
24     }
25 }


我們調整一下TimeDecoder去產生一個UnixTime而不是ByteBuf.

1 @Override
2 protected Object decode(ChannelHandlerContext ctx, ByteBuf in, MessageList<Object> out) {
3     if (in.readableBytes() < 4) {
4         return;
5     }
6  
7     out.add(new UnixTime(buffer.readInt());
8 }


隨着解碼碼更新完成, TimeClientHandler不再使用ByteBuf所以我們需要改一下去接收一個UnixTime類型的消息. 

1 @Override
2 public void messageReceived(ChannelHandlerContext ctx, MessageList<Object> msgs) {
3     UnixTime m = (UnixTime) msgs.get(0);
4     System.out.println(m);
5     ctx.close();
6 }

更簡單和優雅, 對嗎? 同樣的技術可以應用的服務端. 讓我們再更新一下TimeServerHandler: 

1 @Override
2 public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
3     ChannelFuture f = e.getChannel().write(new UnixTime());
4     f.addListener(ChannelFutureListener.CLOSE);
5 }

現在唯一缺少的一塊是編碼器,  這是一個ChannelOutboundHandler的實現, 他將UnixTime轉換爲ByteBuf. 比寫一個解碼器還要簡單因爲當編碼消息時不需要處理分包和裝配的問題.  

01 package io.netty.example.time;
02  
03 public class TimeEncoder extends ChannelOutboundHandlerAdapter {
04     @Override
05     public void write(ChannelHandlerContext ctx, MessageList<Object> msgs, ChannelPromise promise) {
06         MessageList<ByteBuf> out = MessageList.newInstance();
07         for (UnixTime m: msgs.<UnixTime>cast()) {
08             ByteBuf encoded = ctx.alloc().buffer(4);
09             encoded.writeInt(m.value());
10             out.add(encoded);
11         }
12         msgs.releaseAllAndRecycle();
13         ctx.write(out, promise); // (1)
14     }
15 }

1. 注意這裏我們傳進去一個原始參數ChannelPromise, 當數據真正寫入後Netty用他來標記成功還是失敗.  
甚至可以進一步簡化, 你可以用MessageToByteEncoder: 

1 public class TimeEncoder extends MessageToByteEncoder<UnixTime> {
2     @Override
3     protected void encode(ChannelHandlerContext ctx, UnixTime msg, ByteBuf out) {
4         out.writeInt(msg.value());
5     }
6 }

最後留下的任務是在服務端插入TimeEncoder到ChannelPipeline.

關閉你的程序

通過shutdownGracefully()方法關閉Netty程序可以像關閉你創建的EventLoopGroup一樣簡單. 他返回一個Future, 當EventLoopGroup中斷完成後通知你並且屬於"boss"和"worker"組的所有channel會被關閉. 

 

發佈了63 篇原創文章 · 獲贊 28 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章