NIO框架之MINA源碼解析(一):背景
NIO框架之MINA源碼解析(二):mina核心引擎
本文主要介紹下在mina中責任鏈模式的應用以及mina對於數據讀寫的處理。
在mina中,對數據的讀操作是在processor類裏面觸發的,收到新消息後就觸發讀數據鏈去處理新消息直到自己的業務邏輯代碼(IoHandler)。
在mina中,數據的寫(write)和發(send)差別相對較大,mina中的寫消息最終的結果只是把要寫的消息經過寫數據鏈處理後的最終結果放在了一個緩存中,並把當前session標記爲可發。
數據的發送就是傳統中我們所說的發消息,就是把寫消息最終處理的結果發送到客戶端,待發送完成後,就調用發數據鏈進行操作,最後再調用IoHandlerde 發方法。
1、觸發點
1.1、讀數據
讀操作是在Processor中的觸發的,Processor是AbstractPollingIoProcessor的內部私有類。
Processor中有一個死循環,循環調用Selector的select方法,若有新消息,則進行process()。
詳見Processor代碼。
1.2、寫數據
寫操作很簡單,是調用session的write方法,進行寫數據的,寫數據的最終結果保存在一個緩存隊列裏面,等待發送,並把當前session放入flushSession隊列裏面。
1.3、 發數據
發數據其實和讀數據是差不多的,都在Processor中的觸發的,在process()完新消息後,會調用flush()方法,把flushSession隊列裏面的session取出來,並把緩存的消息發送到客戶端。
詳見Processor代碼。
2、責任鏈模式
在mina中,責任鏈模式相關的類都定義在了org.apache.mina.core.filterchain包中,看類圖:
IoFilter接口實現代表一個具體的執行單元,是寫自定義IoFilter的接口,IoFilter有一個適配器IoFilterAdapter,裏面什麼都沒有幹。
NextFilter接口看上去和IoFilter接口差不多,但NextFilter接口代表的是“下一個filter”,這裏的下是抽象的,因爲在mina的各種鏈中,處理順序有的是從頭到尾,有的是從尾到頭,而這裏的下就代表了熟悉中的下一個filter。
Entry接口是鏈接中的具體對象,其封裝了IoFilter接口和NextFilter接口,代表一個實體放在鏈隊列裏面。
DefaultIoFilterChainBuilder是mina提供的一個便於用戶構造IoFilterChain的方法。
2.1、讀數據-責任鏈
2.2、寫數據-責任鏈
2.3、發數據-責任鏈
2.4 責任鏈引擎實現
這裏以讀數據-責任鏈爲例,說下在mina中具體是怎麼實現這個責任鏈的執行。
engin代碼
//class DefaultIoFilterChain
//觸發點,傳入消息對象
public void fireMessageReceived(Object message) {
if (message instanceof IoBuffer) {
session.increaseReadBytes(((IoBuffer) message).remaining(), System.currentTimeMillis());
}
//從頭開始
Entry head = this.head;
callNextMessageReceived(head, session, message);
}
//這個地方是個遞歸調用入口,目的就是執行entry裏面的iofilter,並把當前entry的下一個nextfilter傳入
private void callNextMessageReceived(Entry entry, IoSession session, Object message) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.messageReceived(nextFilter, session, message);
} catch (Throwable e) {
fireExceptionCaught(e);
}
}
iofilter代碼,這裏面拿一個簡單的LoggingFilter來說明
//class LoggingFilter
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
log(messageReceivedLevel, "RECEIVED: {}", message);
//調用nextfilter的receive方法,執行下一個filter
//也可以不調用,直接返回
nextFilter.messageReceived(session, message);
//當然也可以在這裏加一些處理後的業務邏輯。
}
nextfilter代碼
private class EntryImpl implements Entry {
private EntryImpl prevEntry;
private EntryImpl nextEntry;
private final String name;
private IoFilter filter;
private final NextFilter nextFilter;
private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) {
if (filter == null) {
throw new IllegalArgumentException("filter");
}
if (name == null) {
throw new IllegalArgumentException("name");
}
this.prevEntry = prevEntry;
this.nextEntry = nextEntry;
this.name = name;
this.filter = filter;
this.nextFilter = new NextFilter() {
public void messageReceived(IoSession session, Object message) {
Entry nextEntry = EntryImpl.this.nextEntry;
//把nextEntry指向相應的entry,繼續進入循環體,注意這裏的EntryImpl.this.nextEntry,即從頭到尾
callNextMessageReceived(nextEntry, session, message);
}
public void messageSent(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageSent(nextEntry, session, writeRequest);
}
public void filterWrite(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.prevEntry;
//把nextEntry指向相應的entry,繼續進入循環體,注意這裏的EntryImpl.this.prevEntry,即從尾到頭
callPreviousFilterWrite(nextEntry, session, writeRequest);
}
};
}
public String getName() {
return name;
}
public IoFilter getFilter() {
return filter;
}
}