1. 程式人生 > >Java NIO框架Netty教程(三) – Object物件傳遞

Java NIO框架Netty教程(三) – Object物件傳遞

說了這麼多廢話,才提到物件的傳輸,不知道您是不是已經不耐煩了。一個系統內部的訊息傳遞,沒有物件傳遞是不太現實的。下面就來說說,怎麼傳遞物件。

如果,您看過前面的介紹,如果您善於專注本質,勤于思考。您應該也會想到,我們說過,Netty的訊息傳遞都是基於流,通過ChannelBuffer傳遞的,那麼自然,Object也需要轉換成ChannelBuffer來傳遞。好在Netty本身已經給我們寫好了這樣的轉換工具。 ObjectEncoder和ObjectDecoder。

工具怎麼用?再一次說說所謂的本質,我們之前也說過,Netty給我們處理自己業務的空間是在靈活的可子定義的Handler上的,也就是說,如果我們自己去做這個轉換工作,那麼也應該在Handler裡去做。而Netty,提供給我們的ObjectEncoder和Decoder也恰恰是一組 Handler。於是,修改Server和Client的啟動程式碼:

01 02 03 04 05 06 07 08 09 10 // 設定一個處理客戶端訊息和各種訊息事件的類(Handler) bootstrap.setPipelineFactory(newChannelPipelineFactory() { @Override publicChannelPipeline getPipeline()throwsException { returnChannels.pipeline( newObjectDecoder(ClassResolvers.cacheDisabled(this .getClass().getClassLoader())),
newObjectServerHandler()); } });
客戶端
1 2 3 4 5 6 7 8 // 設定一個處理服務端訊息和各種訊息事件的類(Handler) bootstrap.setPipelineFactory(newChannelPipelineFactory() { @Override publicChannelPipeline getPipeline()throwsException { returnChannels.pipeline(newObjectEncoder(), newObjectClientHandler()); } });

要傳遞物件,自然要有一個被傳遞模型,一個簡單的Pojo,當然,實現序列化介面是必須的。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * @author lihzh * @alia OneCoder */ public class Command implementsSerializable { privatestaticfinal long serialVersionUID = 7590999461767050471L; privateString actionName; publicString getActionName() { returnactionName; } publicvoidsetActionName(String actionName) { this.actionName = actionName; } }

服務端和客戶端裡,我們自定義的Handler實現如下:

ObjectServerHandler .java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * 物件傳遞服務端程式碼 * * @author lihzh * @alia OneCoder */ public class ObjectServerHandler extendsSimpleChannelHandler { /** * 當接受到訊息的時候觸發 */ @Override publicvoidmessageReceived(ChannelHandlerContext ctx, MessageEvent e) throwsException { Command command = (Command) e.getMessage(); // 列印看看是不是我們剛才傳過來的那個 System.out.println(command.getActionName()); } }
ObjectClientHandler .java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /** * 物件傳遞,客戶端程式碼 * * @author lihzh * @alia OneCoder */ public class ObjectClientHandler extendsSimpleChannelHandler { /** * 當繫結到服務端的時候觸發,給服務端發訊息。 * * @author lihzh * @alia OneCoder */ @Override publicvoidchannelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { // 向服務端傳送Object資訊 sendObject(e.getChannel()); } /** * 傳送Object * * @param channel * @author lihzh * @alia OneCoder */ privatevoidsendObject(Channel channel) { Command command =newCommand(); command.setActionName("Hello action."); channel.write(command); } }

啟動後,服務端正常列印結果:Hello action.

簡單梳理一下思路:

通過Netty傳遞,都需要基於流,以ChannelBuffer的形式傳遞。所以,Object -> ChannelBuffer.
Netty提供了轉換工具,需要我們配置到Handler。
樣例從客戶端 -> 服務端,單向發訊息,所以在客戶端配置了編碼,服務端解碼。如果雙向收發,則需要全部配置Encoder和Decoder。
這裡需要注意,註冊到Server的Handler是有順序的,如果你顛倒一下注冊順序:

1 2 3 4 5 6 7 8 9 bootstrap.setPipelineFactory(newChannelPipelineFactory() { @Override publicChannelPipeline getPipeline()throwsException { returnChannels.pipeline(newObjectServerHandler(), newObjectDecoder(ClassResolvers.cacheDisabled(this .getClass().getClassLoader())) ); } });

結果就是,會先進入我們自己的業務,再進行解碼。這自然是不行的,會強轉失敗。至此,你應該會用Netty傳遞物件了吧。