设为首页 收藏本站
查看: 949|回复: 0

[经验分享] 深入解析Apache Mina源码(1)——Mina的过滤器机制实现

[复制链接]

尚未签到

发表于 2017-1-14 10:04:02 | 显示全部楼层 |阅读模式
  



1、深入解析Apache Mina源码(1)——Mina的过滤器机制实现


2、深入解析Apache Mina源码(2)——Mina的事件模型

一、责任链模式的本来面目

Mina 中有一个重要的设计模式-责任链模式,它将此模式成功的应用在了它的过滤器链(IoFilterChain)中。开发过J2EE的童鞋们应该对这个模式比较清楚,在Servlet中我们就可以加入Filter的实现,还有Hibernate中也实现了FilterChain。学习怎么实现责任链模式对于我们对开源软件的学习和以后的工作都会有莫大的帮助。
我们知道计算机系统就是接收信息,进行信息处理,信息输出的过程,那么在这个过程中我们加入过滤器有很多好处,消息经过特定功能的多个过滤器进行逐步处理得到所需要的最终信息,让处理过程透明,责任明晰,方便扩展。
责任链模式的定义我也就不说了,网上一大堆,我的理解是可以把它理解成一个有向链表,消息在这个链表中的某个过滤器进行处理然后再传向下个过滤器,在每个过滤器中都可以处理这些消息,也可以不处理。如图:

DSC0000.jpeg
责任链模式的类图如下:

DSC0001.jpg
其实这里面最核心的就是Handler了,它可是是一个接口或者是一个抽象类,它有对自己的一个引用successor,然后有个处理方法HandleRequest()。因为有了对自己的引用successor所以当本对象不能处理的时候可以转向successor.HandleRequest()方法,这样一个“链”就形成了。
你应该挺羡慕富士.康里面生产苹果手机的工人吧,你平时最喜欢的苹果手机就是他们生产出来的,他们一个人就能把苹果手机生产出来吗?不是的,他们是流水线做业的,OK,流水线就可以看做是责任链模式的体现,工人就是链条上的一员,有的工人组装屏幕,有的工人检查手机,有的工人进行手机的包装等,下面我们就以代码的方式实现:
苹果手机类:

package com.lifanghu.chain;
/**
* @author lifh
* @mail wslfh2005@163.com
* @since 2012-6-12 下午11:20:18
* @name com.lifanghu.chain.Iphone.java
* @version 1.0
*/
public class Iphone {
private String state = "我是一台苹果机器;";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}

 

抽象处理接口类:

package com.lifanghu.chain;

/**
* @author  lifh
* @mail    wslfh2005@163.com
* @since   2012-6-12 下午11:23:36
* @name    com.lifanghu.chain.IWorker.java
* @version 1.0
*/
public interface IWorker {
/**
* 处理方法
* @param iphone
* @author lifh
*/
void handleIphone(Iphone iphone);
/**
* 设置下一个处理者
* @param worker
* @author lifh
*/
void setNext(IWorker worker);
}

 

具体处理者:

package com.lifanghu.chain;
/**
* @author lifh
* @mail wslfh2005@163.com
* @since 2012-6-12 下午11:29:46
* @name com.lifanghu.chain.Worker1.java
* @version 1.0
*/
public class Worker1 implements IWorker {
private IWorker next;
public void handleIphone(Iphone iphone) {
iphone.setState(iphone.getState() + "我被装了一个黑色的后盖;");
if (next != null)
next.handleIphone(iphone);
}
public void setNext(IWorker worker) {
this.next = worker;
}
}
package com.lifanghu.chain;
/**
* @author lifh
* @mail wslfh2005@163.com
* @since 2012-6-12 下午11:34:32
* @name com.lifanghu.chain.Worker2.java
* @version 1.0
*/
public class Worker2 implements IWorker {
private IWorker next;
public void handleIphone(Iphone iphone) {
iphone.setState(iphone.getState() + "我被装了一块电池;");
if (next != null)
next.handleIphone(iphone);
}
public void setNext(IWorker worker) {
this.next = worker;
}
}
package com.lifanghu.chain;
/**
* @author lifh
* @mail wslfh2005@163.com
* @since 2012-6-12 下午11:34:32
* @name com.lifanghu.chain.Worker3.java
* @version 1.0
*/
public class Worker3 implements IWorker {
private IWorker next;
public void handleIphone(Iphone iphone) {
iphone.setState(iphone.getState() + "我现在是一台完整的Iphone了。");
if (next != null)
next.handleIphone(iphone);
}
public void setNext(IWorker worker) {
this.next = worker;
}
}

 

客户端调用者:

package com.lifanghu.chain;
/**
* @author lifh
* @mail wslfh2005@163.com
* @since 2012-6-12 下午11:37:27
* @name com.lifanghu.chain.Client.java
* @version 1.0
*/
public class Client {
public static void main(String[] args) {
IWorker worker1 = new Worker1();
IWorker worker2 = new Worker2();
IWorker worker3 = new Worker3();
worker1.setNext(worker2);
worker2.setNext(worker3);
Iphone iphone = new Iphone();
worker1.handleIphone(iphone);
System.out.println(iphone.getState());
}
}

 

输出结果:
 

 写道

我是一台苹果机器;我被装了一个黑色的后盖;我被装了一块电池;我现在是一台完整的Iphone了。

 好了,现在一台苹果就组装完成了,发现了没有,我们的代码比较整洁清新,没有大量的if/else语句,责任清晰明了,调用简单,想要扩展的话只需要再实现IWorker接口即可,这就是使用责任链模式的好处。

二、Mina是怎么实现责任链模式的

上面介绍了纯净的责任链模式,但是在真实的项目中写代码不可能完全照搬,所以多看看开源项目的代码写作方式也许才能真正提高我们的编程能力。就以Mina的过滤器链来看,对这种模式进行了自己的实现,但是道理是相通的,带着责任链模式的理解去看看Mina的实现是怎样的。
先看一下Mina过滤器的类图结构:

DSC0002.jpg
从图中我们可以看出Mina对于此模式的实现是相对比较复杂的,其实从它的代码上也可以看出来,当时也是花了好大力气才把它这块看明白,其实主要在于理清思路,抓住核心类,最主要的一个接口IoFilterChain和它的一个内部接口Entry,其中IoFilterChain代表了过滤器的容器,它本身就是一个对象引用形成的链表结构,默认的实现DefaultIoFilterChain其实有对链表头(head)的引用,找到头后就可以顺着头向下找,一直找到尾(tail),Entry是对IoFilter和NextFilter的封装整合接口,它属于链表IoFilterChain中的元素。指向当前和下一个过滤器。

DSC0003.jpeg
EntryImpl 类中包含两个接口,filter和nextFilter,他们所用的接口是不一样的,至于为什么不用同一个接口,我想可能是因为接口职责单一的原则吧。

DSC0004.jpg

 
虽然有IoFilter和NextFilter两个接口,接口方法都差不多,但最后真正业务的执行者还是IoFilter的实现,IoFilterAdapter做为它的默认实现,完成了适配器的功能,以后的类可以直接继承它而不用实现IoFilter接口,想实现哪个方法只需要覆盖IoFilterAdapter的类的方法即可。NextFilter只起到转发的作用,如消息接收处理方法(messageReceived):
NextFilter的实现:

//消息接收到以后NextFilter的实现会把消息传递给nextEntry去处理。
public void messageReceived(IoSession session, Object message) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageReceived(nextEntry, session, message);
}

 

DefaultIoFilterChain再将消息传递给本Filter的messageReceived方法进行实际的消息接收处理工作:

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);
}
}

 

 
当消息处理完成以后,消息就要进入到业务处理IoHandler的实现类中去完成业务的相关操作了。这可以在链尾看到相关业务传递:

@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
if (!(message instanceof IoBuffer)) {
s.increaseReadMessages(System.currentTimeMillis());
} else if (!((IoBuffer) message).hasRemaining()) {
s.increaseReadMessages(System.currentTimeMillis());
}
try {
// 最后一个filter会进入到handler进行消息处理。
session.getHandler().messageReceived(s, message);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerReadFuture(message);
}
}
}

 

 
至此,Mina的链表结构就基本讲完了,其实仔细看看它的代码还是比较容易理解的,可能里面有些细节还需要我们去琢磨。
链表建立了以后,外界是怎样调用的呢?
在org.apache.mina.core.filterchain包下我们可以看到类IoFilterEvent,可以看到它实现了基于事件的处理模型,当一个事件(比如接收到消息)发生后会触发相应的事件,进而调用过滤器链的消息处理功能进行消息的处理和转发,这块其实会有线程池的参与完成,会在以后的文章中说明这块。
 
 

public void fire() {
IoSession session = getSession();
NextFilter nextFilter = getNextFilter();
IoEventType type = getType();
if (DEBUG) {
LOGGER.debug( "Firing a {} event for session {}",type, session.getId() );
}
switch (type) {
case MESSAGE_RECEIVED:
//触发消息接收
Object parameter = getParameter();
nextFilter.messageReceived(session, parameter);
break;

 当然也可以直接调用:
 

//触发过滤器的接收消息处理
session.getFilterChain().fireMessageReceived(newBuf);

 
 还有一个类DefaultIoFilterChainBuilder,它以用户更易用的角度完成了对过滤器链的封装操作,这里就不细讲了。
总结:本文章主要讲了责任链模式在Mina中的实现,做为一个优秀的框架我们没理由不好好去学习。
每天进步一点点,不做无为的码农。。。。。
2012年6月13日星期三

码农虎虎

http://weibo.com/hurtigf

 

http://www.lifanghu.com/

wslfh2005@163.com

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-328219-1-1.html 上篇帖子: The Apache Tomcat 5.5 Servlet/JSP Container Class Loader HOW-TO 下篇帖子: Apache源代码全景分析第二卷——体系结构和核心模块 目录
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表