zoukankan      html  css  js  c++  java
  • Mina框架Filters

    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

    请求图片的宽度 
    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框架最吸引我的是这种设计思想,将通信、规约解析、业务处理分离得恰到好处,既不影响性能又方便扩展和替换。下一步希望从源代码的角度,学习一下其内部的实现思想。

     
    分类: Java
    标签: MINA
  • 相关阅读:
    Reactive Extensions (Rx) 入门(5) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(4) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions
    Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
    Xamarin NuGet 缓存包导致 already added : Landroid/support/annotation/AnimRes 问题解决方案
    Android 系统Action大全
    Xamarin Forms 实现发送通知点击跳转
    如何理解灰度发布
    推荐一款分布式微服务框架 Surging
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2751280.html
Copyright © 2011-2022 走看看