先啰嗦兩句,如果你還不知道netty是做什麼的能做什麼。那可以先簡單的搜尋了解一下。我隻能說netty是一個nio的架構,可以用于開發分布式的java程式。具體能做什麼,各位可以盡量發揮想象。技術,是服務于人而不是局限住人的。
如果你已經萬事具備,那麼我們先從一段代碼開始。程式員們習慣的上手第一步,自然是"hello world",不過netty官網的例子卻偏偏抛棄了"hello world"。那我們就自己寫一個最簡單的"hello world"的例子,作為上手。
/**
* netty 服務端代碼
*
* @author lihzh
* @alia onecoder
* @blog http://www.coderli.com
*/
public class helloserver {
public static void main(string args[]) {
// server服務啟動器
serverbootstrap bootstrap = new serverbootstrap(
new nioserversocketchannelfactory(
executors.newcachedthreadpool(),
executors.newcachedthreadpool()));
// 設定一個處理用戶端消息和各種消息事件的類(handler)
bootstrap
.setpipelinefactory(new channelpipelinefactory() {
@override
public channelpipeline getpipeline()
throws exception {
return channels
.pipeline(new helloserverhandler());
}
});
// 開放8000端口供用戶端通路。
bootstrap.bind(new inetsocketaddress(8000));
}
private static class helloserverhandler extends
simplechannelhandler {
/**
* 當有用戶端綁定到服務端的時候觸發,列印"hello world, i'm server."
*
* @alia onecoder
* @author lihzh
*/
@override
public void channelconnected(
channelhandlercontext ctx,
channelstateevent e) {
system.out.println("hello world, i'm server.");
}
}
* netty 用戶端代碼
public class helloclient {
// client服務啟動器
clientbootstrap bootstrap = new clientbootstrap(
new nioclientsocketchannelfactory(
// 設定一個處理服務端消息和各種消息事件的類(handler)
bootstrap.setpipelinefactory(new channelpipelinefactory() {
@override
public channelpipeline getpipeline() throws exception {
return channels.pipeline(new helloclienthandler());
}
});
// 連接配接到本地的8000端口的服務端
bootstrap.connect(new inetsocketaddress(
"127.0.0.1", 8000));
private static class helloclienthandler extends simplechannelhandler {
* 當綁定到服務端的時候觸發,列印"hello world, i'm client."
public void channelconnected(channelhandlercontext ctx,
system.out.println("hello world, i'm client.");
既然是分布式的,自然要分多個服務。netty中,需要區分server和client服務。所有的client都是綁定在server上的,他們之間是不能通過netty直接通信的。(自己采用的其他手段,不包括在内。)。白話一下這個通信過程,server端開放端口,供client連接配接,client發起請求,連接配接到server指定的端口,完成綁定。随後便可自由通信。其實就是普通socket連接配接通信的過程。
netty架構是基于事件機制的,簡單說,就是發生什麼事,就找相關處理方法。就跟着火了找119,搶劫了找110一個道理。是以,這裡,我們處理的是當用戶端和服務端完成連接配接以後的這個事件。什麼時候完成的連接配接,netty知道,他告訴我了,我就負責處理。這就是架構的作用。netty,提供的事件還有很多,以後會慢慢的接觸和介紹。
說了這麼多廢話,才提到對象的傳輸,不知道您是不是已經不耐煩了。一個系統内部的消息傳遞,沒有對象傳遞是不太現實的。下面就來說說,怎麼傳遞對象。
如果,您看過前面的介紹,如果您善于專注本質,勤于思考。您應該也會想到,我們說過,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());
});
// 用戶端設定一個處理服務端消息和各種消息事件的類(handler)
return channels.pipeline(new objectencoder(), new objectclienthandler());
要傳遞對象,自然要有一個被傳遞模型,一個簡單的pojo,當然,實作序列化接口是必須的。
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實作如下:
* 對象傳遞服務端代碼
*
public class objectserverhandler extends simplechannelhandler {
/**
* 當接受到消息的時候觸發
*/
public void messagereceived(channelhandlercontext ctx, messageevent e)
throws exception {
command command = (command) e.getmessage();
// 列印看看是不是我們剛才傳過來的那個
system.out.println(command.getactionname());
* 對象傳遞,用戶端代碼
public class objectclienthandler extends simplechannelhandler {
* 當綁定到服務端的時候觸發,給服務端發消息。
public void channelconnected(channelhandlercontext ctx, channelstateevent e) {
// 向服務端發送object資訊
sendobject(e.getchannel());
* 發送object
*
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是有順序的,如果你颠倒一下注冊順序:
new objectserverhandler(),
new objectdecoder(classresolvers.cachedisabled(this.getclass().getclassloader())));
結果就是,會先進入我們自己的業務,再進行解碼。這自然是不行的,會強轉失敗。至此,你應該會用netty傳遞對象了吧。