Java NIO框架Netty教程(三) – Object物件傳遞
說了這麼多廢話,才提到物件的傳輸,不知道您是不是已經不耐煩了。一個系統內部的訊息傳遞,沒有物件傳遞是不太現實的。下面就來說說,怎麼傳遞物件。
如果,您看過前面的介紹,如果您善於專注本質,勤于思考。您應該也會想到,我們說過,Netty的訊息傳遞都是基於流,通過ChannelBuffer傳遞的,那麼自然,Object也需要轉換成ChannelBuffer來傳遞。好在Netty本身已經給我們寫好了這樣的轉換工具。 ObjectEncoder和ObjectDecoder。
工具怎麼用?再一次說說所謂的本質,我們之前也說過,Netty給我們處理自己業務的空間是在靈活的可子定義的Handler上的,也就是說,如果我們自己去做這個轉換工作,那麼也應該在Handler裡去做。而Netty,提供給我們的ObjectEncoder和Decoder也恰恰是一組 Handler。於是,修改Server和Client的啟動程式碼:
// 設定一個處理客戶端訊息和各種訊息事件的類(Handler)
bootstrap.setPipelineFactory(
new
ChannelPipelineFactory() {
@Override
public
ChannelPipeline getPipeline()
throws
Exception
{
return
Channels.pipeline(
new
ObjectDecoder(ClassResolvers.cacheDisabled(
this
.getClass().getClassLoader())),
new
ObjectServerHandler());
}
});
1 2 3 4 5 6 7 8 |
// 設定一個處理服務端訊息和各種訊息事件的類(Handler)
bootstrap.setPipelineFactory( new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline( new ObjectEncoder(),
new ObjectClientHandler());
}
});
|
要傳遞物件,自然要有一個被傳遞模型,一個簡單的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 implements Serializable {
private static final
long serialVersionUID = 7590999461767050471L;
private String actionName;
public String getActionName() {
return actionName;
}
public void setActionName(String actionName) {
this .actionName = actionName;
}
}
|
服務端和客戶端裡,我們自定義的Handler實現如下:
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 extends SimpleChannelHandler {
/**
* 當接受到訊息的時候觸發
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
Command command = (Command) e.getMessage();
// 列印看看是不是我們剛才傳過來的那個
System.out.println(command.getActionName());
}
}
|
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 extends SimpleChannelHandler {
/**
* 當繫結到服務端的時候觸發,給服務端發訊息。
*
* @author lihzh
* @alia OneCoder
*/
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// 向服務端傳送Object資訊
sendObject(e.getChannel());
}
/**
* 傳送Object
*
* @param channel
* @author lihzh
* @alia OneCoder
*/
private void sendObject(Channel channel) {
Command command = new Command();
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( new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline( new ObjectServerHandler(),
new ObjectDecoder(ClassResolvers.cacheDisabled( this
.getClass().getClassLoader()))
);
}
});
|
結果就是,會先進入我們自己的業務,再進行解碼。這自然是不行的,會強轉失敗。至此,你應該會用Netty傳遞物件了吧。