說了這么多廢話,才提到對(duì)象的傳輸,不知道您是不是已經(jīng)不耐煩了。一個(gè)系統(tǒng)內(nèi)部的消息傳遞,沒有對(duì)象傳遞是不太現(xiàn)實(shí)的。下面就來說說,怎么傳遞對(duì)象。
如果,您看過前面的介紹,如果您善于專注本質(zhì),勤于思考。您應(yīng)該也會(huì)想到,我們說過,Netty的消息傳遞都是基于流,通過ChannelBuffer傳遞的,那么自然,Object也需要轉(zhuǎn)換成ChannelBuffer來傳遞。好在Netty本身已經(jīng)給我們寫好了這樣的轉(zhuǎn)換工具。ObjectEncoder和ObjectDecoder。
工具怎么用?再一次說說所謂的本質(zhì),我們之前也說過,Netty給我們處理自己業(yè)務(wù)的空間是在靈活的可子定義的Handler上的,也就是說,如果我們自己去做這個(gè)轉(zhuǎn)換工作,那么也應(yīng)該在Handler里去做。而Netty,提供給我們的ObjectEncoder和Decoder也恰恰是一組Handler。于是,修改Server和Client的啟動(dòng)代碼:
01 02 03 04 05 06 07 08 09 10 | // 設(shè)置一個(gè)處理客戶端消息和各種消息事件的類(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 | // 設(shè)置一個(gè)處理服務(wù)端消息和各種消息事件的類(Handler) bootstrap.setPipelineFactory( new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline( new ObjectEncoder(), new ObjectClientHandler()); } }); |
要傳遞對(duì)象,自然要有一個(gè)被傳遞模型,一個(gè)簡(jiǎn)單的Pojo,當(dāng)然,實(shí)現(xiàn)序列化接口是必須的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** * @author lihzh * @alia OneCoder * @blog http://www.coderli.com */ 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; } } |
服務(wù)端和客戶端里,我們自定義的Handler實(shí)現(xiàn)如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * 對(duì)象傳遞服務(wù)端代碼 * * @author lihzh * @alia OneCoder * @blog http://www.coderli.com */ public class ObjectServerHandler extends SimpleChannelHandler { /** * 當(dāng)接受到消息的時(shí)候觸發(fā) */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Command command = (Command) e.getMessage(); // 打印看看是不是我們剛才傳過來的那個(gè) 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 | /** * 對(duì)象傳遞,客戶端代碼 * * @author lihzh * @alia OneCoder * @blog http://www.coderli.com */ public class ObjectClientHandler extends SimpleChannelHandler { /** * 當(dāng)綁定到服務(wù)端的時(shí)候觸發(fā),給服務(wù)端發(fā)消息。 * * @author lihzh * @alia OneCoder */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { // 向服務(wù)端發(fā)送Object信息 sendObject(e.getChannel()); } /** * 發(fā)送Object * * @param channel * @author lihzh * @alia OneCoder */ private void sendObject(Channel channel) { Command command = new Command(); command.setActionName( "Hello action." ); channel.write(command); } } |
啟動(dòng)后,服務(wù)端正常打印結(jié)果:Hello action.
簡(jiǎn)單梳理一下思路:
這里需要注意,注冊(cè)到Server的Handler是有順序的,如果你顛倒一下注冊(cè)順序:
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())) ); } }); |
結(jié)果就是,會(huì)先進(jìn)入我們自己的業(yè)務(wù),再進(jìn)行解碼。這自然是不行的,會(huì)強(qiáng)轉(zhuǎn)失敗。至此,你應(yīng)該會(huì)用Netty傳遞對(duì)象了吧。
聯(lián)系客服