黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

深入理解Apache Mina (2)---- 與IoFilter相關(guān)

系統(tǒng) 1916 0

從名字上看知道IoFilter應(yīng)該是一個過濾器,不錯,它確實是一個過濾器,它和Servlet中的過濾器類似,主要用于攔截和過濾I/O操作中的各種信息。在Mina的官方文檔中已經(jīng)提到了IoFilter的作用:
(1)記錄事件的日志(這個在本文中關(guān)于LoggingFilter的講述中會提到)
(2)測量系統(tǒng)性能
(3)信息驗證
(4)過載控制
(5)信息的轉(zhuǎn)換 (例如:編碼和解碼,這個會在關(guān)于ProtocolCodecFilter的講述中會提到)
(6)和其他更多的信息

?

還是上一篇文檔一樣,先提出幾個問題,然后沿著這幾個問題的思路一個一個的對IoFilter進行講解。
? (1)什么時候需要用到IoFilter,如果在自己的應(yīng)用中不添加過濾器可以嗎?
? (2)如果在IoService中添加多個過濾器可以嗎?若可以,如何進行添加,這多個過濾??
?????? 器是如何工作的?
? (3)Mina中提供了協(xié)議編、解碼器,IoFilter也可以實現(xiàn)IO數(shù)據(jù)的編解碼功能,在實際
?????? 的使用中如何選擇?
?
在開始對上面的問題進行討論前,為了對IoFilter提供的方法有一個具體的了解,先對Mina自身提供的一個最簡單的過濾器進行一些講解----LoggingFilter(源碼在附件中,配有中文翻譯)。

?

首先還是看一下LoggingFilter中提供的幾個方法。列舉如下(方法中的參數(shù)就不再給出,完整方法的實現(xiàn)請參考附件中LoggingFilter的源碼):
(1)sessionCreated()
(2)sessionOpened()
(3)sessionClosed()
(4)sessionIdle()
(5)exceptionCaught()
(6)messageReceived()
(7)messageSent()
(8)filterWrite()
(9)filterClose()
這幾個方法都由相應(yīng)會話(或者說是連接的狀態(tài),讀、寫、空閑、連接的開閉等)的狀態(tài)的改變來觸發(fā)的。當一個會話開啟時,LoggingFilter捕獲到會話開啟的事件,會觸發(fā)sessionCreated()方法,記錄該會話開啟的日志信息。同樣當一個會話發(fā)送數(shù)據(jù)時,Logging捕獲到會話發(fā)送消息的事件會記錄消息發(fā)送的日志信息。這里只是給出messageReceived()的完成方法的實現(xiàn),其他方法的完整實現(xiàn)請參考附件中LoggingFilter的源碼。

?

?/**
? * 記錄會話接收信息時的信息,然后將該信息傳遞到過濾器鏈中的下一個過濾器
? * */
?public void messageReceived(NextFilter nextFilter, IoSession session,
???Object message) {
??if (SessionLog.isInfoEnabled(session)) {
???SessionLog.info(session, "RECEIVED: " + message);
??}
??nextFilter.messageReceived(session, message);
?}?


LoggingFilter繼承與IoFilterAdpater,IoFilterAdpater是IoFilter的一個實現(xiàn)類,該類只是提供了IoFilter方法的簡單實現(xiàn)----將傳遞到各方法中的消息轉(zhuǎn)發(fā)到下一個過濾器中。你可以根據(jù)自己的需求繼承IoFilterAdpater,并重寫相關(guān)的方法。LoggingFilter就是重寫了上面提到的幾個方法,用于記錄當前的會話各種操作的日志信息。通過上面的例子,我們可以大體的了解了IoFilter的基本功能:根據(jù)當前會話狀態(tài),來捕獲和處理當前會話中所傳遞的消息。

?

IoFilter的UML圖如下:

?

從上面的類圖我們可以清晰的看到IoFilter是一個接口,它有兩個具體的實現(xiàn)類:


IoFilterAdpater:該類提供了IoFilter所有方法的方法體,但是沒有任何邏輯處理,你可以根據(jù)你具體的需求繼承該類,并重寫相關(guān)的方法。IoFilterAdpater是在過濾器中使用的較多的一個類。


ReferenceCountingIoFilter:該類封裝IoFilter的實例,它使用監(jiān)視使用該IoFilter的對象的數(shù)量,當沒有任何對象使用該IoFilter時,該類會銷毀該IoFilter。


IoFilterAdpater有三個子類,它們的作用分別如下:
LoggingFilter:日志工具,該類處理記錄IoFilter每個狀態(tài)觸發(fā)時的日志信息外不對數(shù)據(jù)做任何處理。它實現(xiàn)了IoFilter接口的所有方法。你可以通過閱讀該類的源碼學(xué)習(xí)如何實現(xiàn)你自己的IoFilter。


ExcuterFilter:這個Mina自身提供的一個線程池,在Mina中你可以使用這個類配置你自己的線程池,由于創(chuàng)建和銷毀一個線程,需要耗費很多資源,特別是在高性能的程序中這點尤其重要,因此在你的程序中配置一個線程池是很重要的。它有助于你提高你的應(yīng)用程序的性能。關(guān)于配置Mina的線程池在后續(xù)的文檔中會給出詳細的配置方法。


ProtocolFilter:該類是Mina提供的一個協(xié)議編解碼器,在socket通信中最重要的就是協(xié)議的編碼和解碼工作,Mina提供了幾個默認的編解碼器的實現(xiàn),在下面的例子中使用了ObjectSerializationCodecFactory,這是Mina提供的一個Java對象的序列化和反序列化方法。使用這個編解碼器,你可以在你的Java客戶端和服務(wù)器之間傳遞任何類型的Java對象。但是對于不同的平臺之間的數(shù)據(jù)傳遞需要自己定義編解碼器,關(guān)于這點的介紹會在后續(xù)的文檔中給出。

?

為了更加清楚的理解這個過濾器的作用我們先來看一個簡單的例子,這個例子的功能就是服務(wù)器在客戶端連接到服務(wù)器時創(chuàng)建一個會話,然后向客戶端發(fā)送一個字符串(完整的源碼在附件中,這里只給出程序的簡要內(nèi)容):

    
      ServerMain:
public class ServerMain {

 public static void main(String[] args) throws IOException {
  SocketAddress address = new InetSocketAddress("localhost", 4321);
  IoAcceptor acceptor = new SocketAcceptor();
  IoServiceConfig config = acceptor.getDefaultConfig();

  // 配置數(shù)據(jù)的編解碼器
  config.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));

  // 綁定服務(wù)器端口
  acceptor.bind(address, new ServerHandler());
  System.out.println("  服務(wù)器開始在 8000 端口監(jiān)聽 .......");
 }
}
 
ServerHandler:
public class ServerHandler extends IoHandlerAdapter {

 // 創(chuàng)建會話
 public void sessionOpened(IoSession session) throws Exception {
  System.out.println("  服務(wù)器創(chuàng)建了會話  ");
  session.write("  服務(wù)器創(chuàng)建會話時發(fā)送的信息 。");
 }

 // 發(fā)送信息
 public void messageSent(IoSession session, Object message) throws Exception {
 }

 // 接收信息
 public void messageReceived(IoSession session, Object message)
   throws Exception {
 }
}
 
ClientMain:
public class ClientMain {

 public static void main(String[] args) {

  SocketAddress address = new InetSocketAddress("localhost", 4321);
  IoConnector connector = new SocketConnector();
  IoServiceConfig config = connector.getDefaultConfig();

  // 配置數(shù)據(jù)的編解碼器
  config.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
  
  config.getFilterChain().addLast("logger", new LoggingFilter());

  // 連接到服務(wù)器
  connector.connect(address, new ClientHandler());
  System.out.println(" 已經(jīng)連接到了服務(wù)器 " + address);
 }
}
 
ClientHandler:
public class ClientHandler extends IoHandlerAdapter {

 // 發(fā)送信息
 public void messageSent(IoSession session, Object message) throws Exception {
 }

 // 接收信息
 public void messageReceived(IoSession session, Object message)
   throws Exception {
  System.out.println("  客戶端接收到的服務(wù)器的信息是  " + message);
 }
} 

    
  

?

其中ServerMain和ClientMain分別是服務(wù)器和客戶端的主程序,ServerHandler和ClientHandler是服務(wù)器和客戶端的數(shù)據(jù)處理句柄,關(guān)于IoHandler會在后面的文檔中做詳細的講解,這里只是簡單說明一下,IoHandler主要是對數(shù)據(jù)進行邏輯操作,也可以理解為程序的業(yè)務(wù)邏輯層。其中:

    
      // 配置數(shù)據(jù)的編解碼器
  config.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(new ObjectSerializationCodecFactory())); 
    
  

?
這行代碼的功能是將網(wǎng)絡(luò)傳輸中的數(shù)據(jù)在發(fā)送時編碼成二進制數(shù)據(jù),解碼時將二進制數(shù)據(jù)還原成一個對象或者是基本類型的數(shù)據(jù)。

    
      運行這個程序會得到如下結(jié)果:
 已經(jīng)連接到了服務(wù)器 localhost/127.0.0.1:4321
2009-7-9 23:36:46 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] CREATED
2009-7-9 23:36:46 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] OPENED
2009-7-9 23:36:46 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] RECEIVED:   服務(wù)器創(chuàng)建會話時發(fā)送的信息 。
  客戶端接收到的服務(wù)器的信息是    服務(wù)器創(chuàng)建會話時發(fā)送的信息 。 
    
  

?
其中的紅字部分是LoggingFilter打印出的事件信息。黑體部分是程序中System.out的輸出。在ClientMain中的這兩行代碼是向過濾器鏈中添加IoFilter:

    
        // 配置數(shù)據(jù)的編解碼器
  config.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
  config.getFilterChain().addLast("logger", new LoggingFilter());//添加日志工具 
    
  

?

上圖表示了數(shù)據(jù)在本程序中通過過濾器鏈的過程,日志過濾器是根據(jù)會話(IoSession)的狀態(tài)(創(chuàng)建、開啟、發(fā)送、接收、異常等等)來記錄會話的事件信息的,編解碼器是根據(jù)會話的接收和發(fā)送數(shù)據(jù)來觸發(fā)事件的,從這里我們也可以了解通過過濾器我們可以專門針對會話的某個或某幾個狀態(tài)來專門處理相關(guān)的事件,如異常事件,我們可以專門定義一個Exception的IoFilter來處理Mina在通信中所發(fā)生的異常信息。

?

還有一個比較有意思的問題是,假如我們將上面過濾器的順序該成下面的樣子:

    
        config.getFilterChain().addLast("logger", new LoggingFilter());//添加日志工具
        // 配置數(shù)據(jù)的編解碼器
  config.getFilterChain().addLast("codec",
    new ProtocolCodecFilter(new ObjectSerializationCodecFactory())); 


程序的執(zhí)行結(jié)果如下:
 已經(jīng)連接到了服務(wù)器 localhost/127.0.0.1:4321
2009-7-10 0:30:12 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] CREATED
2009-7-10 0:30:12 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] OPENED
2009-7-10 0:30:12 org.apache.mina.util.SessionLog info
信息: [localhost/127.0.0.1:4321] RECEIVED: DirectBuffer[pos=0 lim=56 cap=1024: 00 00 00 34 AC ED 00 05 74 00 2D 20 20 E6 9C 8D E5 8A A1 E5 99 A8 E5 88 9B E5 BB BA E4 BC 9A E8 AF 9D 

E6 97 B6 E5 8F 91 E9 80 81 E7 9A 84 E4 BF A1 E6 81 AF 20 E3 80 82]
  客戶端接收到的服務(wù)器的信息是    服務(wù)器創(chuàng)建會話時發(fā)送的信息 。 

    
  

?
很明顯的是在順序變化了之后,日志中多了接收到的二進制數(shù)據(jù),這是因為在上面數(shù)據(jù)已經(jīng)有解碼器將數(shù)據(jù)還原成了Java對象,所以我們就看不到二進制數(shù)據(jù)了,而在順序變換后,由于先執(zhí)行的是打印信息,此時的數(shù)據(jù)還沒有還原成java對象,所以接收到的數(shù)據(jù)是二進制的。

?

在上面的例子中我們清楚了整個IoFilter或者是IoFilter的工作流程,那么IoFilter在Mina中的作用如何?所有的數(shù)據(jù)在發(fā)送到Mina程序中時,數(shù)據(jù)都是先通過IoFilter,經(jīng)過處理后再轉(zhuǎn)發(fā)到業(yè)務(wù)層。這里IoFilter就起到了一個承上啟下的作用。

?

到這里我們就可以回答本文開始提到的問題了:


?(1)什么時候需要用到IoFilter,如果在自己的應(yīng)用中不添加過濾器可以嗎?
在你自己的程序中可以添加過濾器,也可以不添加,但是在數(shù)據(jù)發(fā)送之前,所發(fā)送的數(shù)據(jù)必須轉(zhuǎn)換成二進制數(shù)據(jù),這個可以有IoFilter完成,也可以由ProtocolCodecFilter完成(關(guān)于這個問題會在后面的文章中詳細講述),否則Mina會拋出Write requests must be transformed to class org.apache.mina.common.ByteBuffer: 異常。這是因為網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)只能是二進制數(shù)據(jù)。因此無論添加不添加過濾器,都必須將要發(fā)送的數(shù)據(jù)轉(zhuǎn)換成二進制數(shù)據(jù)。


(2)如果在IoService中添加多個過濾器可以嗎?若可以,如何進行添加,這多個過濾器是如何工作的?
???? 在IoService中可以添加多個過濾器,這個在上面的程序中已經(jīng)給處理,添加的方式也很簡單,通過程序一目了然。


(3)Mina中提供了協(xié)議編、解碼器,IoFilter也可以實現(xiàn)IO數(shù)據(jù)的編解碼功能,在實際的使用中如何選擇?
???? Mina的編解碼器在Mina的使用中是最關(guān)鍵的一個問題,特別是在不同語言之間進行通信的時候,比如Java和C/C++等,由于Mina自身沒有提供這些編解碼器,所以需要自己來實現(xiàn)。Mina提供了一個Decoder/Encoder,你可以實現(xiàn)兩個類來完成不同平 之間的通信。關(guān)于這個問題會在后面的文檔給出具體的實習(xí)方法。

?

至此,關(guān)于IoFilter的作用就講述完了,希望對你能有所幫助。:)

深入理解Apache Mina (2)---- 與IoFilter相關(guān)的幾個類


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論