Mina框架研究(3)


 

Filters

IoFilter 是MINA框架中一個核心的部分,如下圖,對間於IoService和IoHandle之間,用於過濾所有的I/O事件和請求,其扮演的角色就像J2EE中的Servlet。

mina_app_arch

MINA提供不少現成的過濾器:

1、LoggingFilter :日志過濾器,用於記錄所有的事件和請求日志.

2、ProtocolCodecFilter:規約解析過濾器,用來將所有收到的ByteBuffer內容轉換為POJO消息(對象),實現往來報文的編碼和解碼;

3、CompressionFilter:壓縮過濾器;

4、SSLFilter

 

ProtocolCodecFilter

相對比較常用的是ProtocolCodecFilter,下面主要介紹一下ProtocolCodecFilter的使用:

還是以官方幫助文檔中例子來說明(http://mina.apache.org/chapter-11-codec-filter.html)

這是一個圖片服務器程序,請求圖片的下行報文格式:

image

 

width: 請求圖片的寬度
height: 請求圖片的高度
numchars: 生成的字節個數

 

服務端返回兩張圖片:

image

length1: 圖片1的大小
image1: 圖片1(PNG格式)
length2: 圖片2的大小

image2: 圖片2(PNG格式)

 

現在如果想通過MINA框架來實現基於這一簡單規約的編解碼通信功能,應該如何做呢?

   1: public class ImageServer {
   2:     public static final int PORT = 33789;
   3:  
   4:     public static void main(String[] args) throws IOException {
   5:         ImageServerIoHandler handler = new ImageServerIoHandler();
   6:         NioSocketAcceptor acceptor = new NioSocketAcceptor();
   7:         acceptor.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new ImageCodecFactory(false)));
   8:         acceptor.setLocalAddress(new InetSocketAddress(PORT));
   9:         acceptor.setHandler(handler);
  10:         acceptor.bind();
  11:         System.out.println("server is listenig at port " + PORT);
  12:     }
  13: }

這里先來看和Filter有關的部分:

acceptor.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new ImageCodecFactory(false)));
在acceptor的Filter鏈中加入我們自己的過濾器,一個ProtocolCodecFilter的實現,這里的ImageCodecFactory又是什么呢?
   1: public class ImageCodecFactory implements ProtocolCodecFactory {
   2:     private ProtocolEncoder encoder;
   3:     private ProtocolDecoder decoder;
   4:  
   5:     public ImageCodecFactory(boolean client) {
   6:         if (client) {
   7:             encoder = new ImageRequestEncoder();
   8:             decoder = new ImageResponseDecoder();
   9:         } else {
  10:             encoder = new ImageResponseEncoder();
  11:             decoder = new ImageRequestDecoder();
  12:         }
  13:     }
  14:  
  15:     public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception {
  16:         return encoder;
  17:     }
  18:  
  19:     public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception {
  20:         return decoder;
  21:     }
  22: }
ImageCodecFactory是對接口ProtocolCodecFactory 的實現,是用來構建Filter的。ProtocolCodecFactory 接口只有兩個方法:
   1: public interface ProtocolCodecFactory {
   2:  
   3:     public ProtocolEncoder getEncoder(IoSession is) throws Exception;
   4:  
   5:     public ProtocolDecoder getDecoder(IoSession is) throws Exception;
   6: }
   7:  

沒錯,這個規約編解碼工廠需要裝配一個編碼器(Encoder)和一個解碼器(Decoder):

編碼器:

   1: public class ImageRequestEncoder implements ProtocolEncoder {
   2:  
   3:     public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
   4:         ImageRequest request = (ImageRequest) message;
   5:         IoBuffer buffer = IoBuffer.allocate(12, false);
   6:         buffer.putInt(request.getWidth());
   7:         buffer.putInt(request.getHeight());
   8:         buffer.putInt(request.getNumberOfCharacters());
   9:         buffer.flip();
  10:         out.write(buffer);
  11:     }
  12:  
  13:     public void dispose(IoSession session) throws Exception {
  14:         // nothing to dispose
  15:     }
  16: }

解碼器:

   1: public class ImageRequestDecoder extends CumulativeProtocolDecoder {
   2:  
   3:     protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
   4:         if (in.remaining() >= 12) {
   5:             int width = in.getInt();
   6:             int height = in.getInt();
   7:             int numberOfCharachters = in.getInt();
   8:             ImageRequest request = new ImageRequest(width, height, numberOfCharachters);
   9:             out.write(request);
  10:             return true;
  11:         } else {
  12:             return false;
  13:         }
  14:     }
  15: }

這里解碼器不是直接從ProtocolDecoder繼承的,為什么呢?因為實際中接受的一個數據包並不能保證包含完整的一幀報文,就是所謂的斷幀的情況,如果用CumulativeProtocolDecoder,就不需要自己處理這種情況了,MINA框架會將未解碼的數據保留,等下一包數據到來后繼續嘗試解碼;

這里編碼器的encode和解碼器的doDecode方法就是實際用來進行應用層規約編解碼的;其中ImageResuest是下行請求規約對應POJO.

整個類的協助關系如下圖所示:

 

Main2

 

Filter過濾器處理完后,就交給Handler,做進一步業務處理;

Response部分的就不多羅嗦了,可以看這里

至此對MINA框架用過的一些東西,從使用指南的角度做了一些總結,還有很多方面還沒有用過,先留一個坑,等來日填補吧。MINA框架最吸引我的是這種設計思想,將通信、規約解析、業務處理分離得恰到好處,既不影響性能又方便擴展和替換。下一步希望從源代碼的角度,學習一下其內部的實現思想。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM