mina框架分析:mina Filter

Mina中的过滤器处于IoService与IoHandler之间,用于过滤每一个I/O事件。本文分析Mina中的过滤器是怎么串起来的?

前面提到了IoFilter,FilterChain等接口和类,在分析过滤器链怎么串起来之前,有必要看一下这些接口和类之间的关系。


如上图所示:

FilterChain是由一个个Entry串起来的,EntryImpl是Entry的实现;

从EntryImpl中可以获取到Filter与NextFilter,NextFilter相当于那根线(指针);

有两个特殊的Entry,里面的Filter分别是HeadFilter和TailFilter,我们添加的Filter都处于这两个Filter之间;

每做完一个Entry,NextFilter会回到FilterChain处理下一个Entry(处理顺序如下图所示)。


由上图可知:

(1)当消息到来时,触发过滤器链的fireXXX事件(这一步一般在processor里面触发);

(2)从过滤器链获取上头结点Entry,从头结点Entry中取出filter和nextFilter;

(3)Filter处理后,交由nextFilter处理,nextFilter并不是一个真正的Filter,它决定这个过滤器链的走向,在这里它是返回到过滤器链;

(4)过滤器链通过nextFilter指针得到下一个entry,重复执行(2)、(3),直到每个Entry都处理完。

这里抛出两个问题:

1、如何保证新加入的过滤器在HeadFilter与TailFilter之间?

2、nextFilter一定是从左向右的顺序吗?

3、TailFilter调用了IoHandler吗?

对于第一个问题,答案在EntryImpl的构造方法里面


  1. // EntryImpl构造方法  
  2. private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) {  
  3.         ......  
  4.     this.prevEntry = prevEntry;  
  5.     this.nextEntry = nextEntry;  
  6.     this.name = name;  
  7.     this.filter = filter;  
  8.     this.nextFilter = new NextFilter() {  
  9.         ......  
  10.     };  
  11. }  
  12.   
  13. //FilterChain构造方法  
  14. public DefaultIoFilterChain(AbstractIoSession session) {  
  15.     if (session == null) {  
  16.         throw new IllegalArgumentException("session");  
  17.     }  
  18.   
  19.     this.session = session;  
  20.     head = new EntryImpl(nullnull"head"new HeadFilter());  
  21.     tail = new EntryImpl(head, null"tail"new TailFilter());  
  22.     head.nextEntry = tail;  
  23. }  
在FilterChain构造方法里面初始化了两个Entry:


我们一般调用IoFilterChain的如下方法添加过滤器


  1. void addFirst(String name, IoFilter filter);  
  2. void addLast(String name, IoFilter filter);  
  3. void addBefore(String baseName, String name, IoFilter filter);  
  4. void addAfter(String baseName, String name, IoFilter filter);  
这里以addLast为例,先看看addLast方法的实现

[java]  view plain copy print ?
  1. public synchronized void addFirst(String name, IoFilter filter) {  
  2.     checkAddable(name);  
  3.     register(head, name, filter);  
  4. }  
  5.   
  6. private void register(EntryImpl prevEntry, String name, IoFilter filter) {  
  7.     EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry, name, filter);  
  8.     ......  
  9.     prevEntry.nextEntry.prevEntry = newEntry;  
  10.     prevEntry.nextEntry = newEntry;  
  11.     name2entry.put(name, newEntry);  
  12.     ......  
  13. }  
从代码一目了然,这就是一个简单的链表操作,在这里第一个问题回答完毕。

对于第二个问题答案是否定的。从IoFilter接口可以看出,一共处理以下几种事件:

sessionCreated
sessionOpened
sessionClosed
sessionIdle
exceptionCaught
messageReceived
messageSent
filterClose
filterWrite
前面FilterChain的构造方法中,省略了NextFilter的实现,这里补上


  1. this.nextFilter = new NextFilter() {  
  2.      public void sessionCreated(IoSession session) {  
  3.          Entry nextEntry = EntryImpl.this.nextEntry;  
  4.          callNextSessionCreated(nextEntry, session);  
  5.      }  
  6.   
  7.      public void sessionOpened(IoSession session) {  
  8.          Entry nextEntry = EntryImpl.this.nextEntry;  
  9.          callNextSessionOpened(nextEntry, session);  
  10.      }  
  11.   
  12.      public void sessionClosed(IoSession session) {  
  13.          Entry nextEntry = EntryImpl.this.nextEntry;  
  14.          callNextSessionClosed(nextEntry, session);  
  15.      }  
  16.   
  17.      public void sessionIdle(IoSession session, IdleStatus status) {  
  18.          Entry nextEntry = EntryImpl.this.nextEntry;  
  19.          callNextSessionIdle(nextEntry, session, status);  
  20.      }  
  21.   
  22.      public void exceptionCaught(IoSession session, Throwable cause) {  
  23.          Entry nextEntry = EntryImpl.this.nextEntry;  
  24.          callNextExceptionCaught(nextEntry, session, cause);  
  25.      }  
  26.   
  27.      public void messageReceived(IoSession session, Object message) {  
  28.          Entry nextEntry = EntryImpl.this.nextEntry;  
  29.          callNextMessageReceived(nextEntry, session, message);  
  30.      }  
  31.   
  32.      public void messageSent(IoSession session, WriteRequest writeRequest) {  
  33.          Entry nextEntry = EntryImpl.this.nextEntry;  
  34.          callNextMessageSent(nextEntry, session, writeRequest);  
  35.      }  
  36.   
  37.      public void filterWrite(IoSession session, WriteRequest writeRequest) {  
  38.          Entry nextEntry = EntryImpl.this.prevEntry;  
  39.          callPreviousFilterWrite(nextEntry, session, writeRequest);  
  40.      }  
  41.   
  42.      public void filterClose(IoSession session) {  
  43.          Entry nextEntry = EntryImpl.this.prevEntry;  
  44.          callPreviousFilterClose(nextEntry, session);  
  45.      }  

可以看出filterWrite与filterClose是反向的,其他都是正向的。

对于第三个问题,直接看TailFilter的代码即可:


  1. public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {  
  2.     AbstractIoSession s = (AbstractIoSession) session;  
  3.     if (!(message instanceof IoBuffer)) {  
  4.         s.increaseReadMessages(System.currentTimeMillis());  
  5.     } else if (!((IoBuffer) message).hasRemaining()) {  
  6.         s.increaseReadMessages(System.currentTimeMillis());  
  7.     }  
  8.   
  9.     try {  
  10.         session.getHandler().messageReceived(s, message);  
  11.     } finally {  
  12.         if (s.getConfig().isUseReadOperation()) {  
  13.             s.offerReadFuture(message);  
  14.         }  
  15.     }  
  16. }  
确实调用了handler来处理真正的请求。

总结一下:FilterChain是由Entry组成一个链表,HeadFilter与TailFilter所在Entry分别是链表的首尾,HeadFilter与processor相连,TailFilter与handler相连,添加Filter的操作实际上是普通的链表插入操作。FilterChain可以触发多种事件,每种事件到来时Filter的顺序是正序还是倒序由nextFilter决定。
原文转载于:http://blog.youkuaiyun.com/aesop_wubo/article/details/9391033
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值