Apache 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的构造方法里面
// EntryImpl构造方法
private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) {
......
this.prevEntry = prevEntry;
this.nextEntry = nextEntry;
this.name = name;
this.filter = filter;
this.nextFilter = new NextFilter() {
......
};
} //FilterChain构造方法
public DefaultIoFilterChain(AbstractIoSession session) {
if (session == null) {
throw new IllegalArgumentException("session");
} this.session = session;
head = new EntryImpl(null, null, "head", new HeadFilter());
tail = new EntryImpl(head, null, "tail", new TailFilter());
head.nextEntry = tail;
}
在FilterChain构造方法里面初始化了两个Entry:
我们一般调用IoFilterChain的如下方法添加过滤器
void addFirst(String name, IoFilter filter);
void addLast(String name, IoFilter filter);
void addBefore(String baseName, String name, IoFilter filter);
void addAfter(String baseName, String name, IoFilter filter);
这里以addLast为例,先看看addLast方法的实现
public synchronized void addFirst(String name, IoFilter filter) {
checkAddable(name);
register(head, name, filter);
}
private void register(EntryImpl prevEntry, String name, IoFilter filter) {
EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry, name, filter);
......
prevEntry.nextEntry.prevEntry = newEntry;
prevEntry.nextEntry = newEntry;
name2entry.put(name, newEntry);
......
}
从代码一目了然,这就是一个简单的链表操作,在这里第一个问题回答完毕。
对于第二个问题答案是否定的。从IoFilter接口可以看出,一共处理以下几种事件:
sessionCreated
sessionOpened
sessionClosed
sessionIdle
exceptionCaught
messageReceived
messageSent
filterClose
filterWrite
前面FilterChain的构造方法中,省略了NextFilter的实现,这里补上
this.nextFilter = new NextFilter() {
public void sessionCreated(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionCreated(nextEntry, session);
}
public void sessionOpened(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionOpened(nextEntry, session);
}
public void sessionClosed(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionClosed(nextEntry, session);
}
public void sessionIdle(IoSession session, IdleStatus status) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionIdle(nextEntry, session, status);
}
public void exceptionCaught(IoSession session, Throwable cause) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextExceptionCaught(nextEntry, session, cause);
}
public void messageReceived(IoSession session, Object message) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageReceived(nextEntry, session, message);
}
public void messageSent(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageSent(nextEntry, session, writeRequest);
}
public void filterWrite(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.prevEntry;
callPreviousFilterWrite(nextEntry, session, writeRequest);
}
public void filterClose(IoSession session) {
Entry nextEntry = EntryImpl.this.prevEntry;
callPreviousFilterClose(nextEntry, session);
}
}
可以看出filterWrite与filterClose是反向的,其他都是正向的。
对于第三个问题,直接看TailFilter的代码即可:
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 {
session.getHandler().messageReceived(s, message);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerReadFuture(message);
}
}
}
确实调用了handler来处理真正的请求。
总结一下:FilterChain是由Entry组成一个链表,HeadFilter与TailFilter所在Entry分别是链表的首尾,HeadFilter与processor相连,TailFilter与handler相连,添加Filter的操作实际上是普通的链表插入操作。FilterChain可以触发多种事件,每种事件到来时Filter的顺序是正序还是倒序由nextFilter决定。
Apache Mina Filter的更多相关文章
- Apache MiNa 实现多人聊天室
Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...
- Apache Mina(一)
原文链接:http://www.cnblogs.com/xuekyo/archive/2013/03/06/2945826.html Apache Mina是一个能够帮助用户开发高性能和高伸缩性网络应 ...
- Apache Mina 入门实例
这个教程是介绍使用Mina搭建基础示例.这个教程内容是以创建一个时间服务器. 以下是这个教程需要准备的东西: MINA 2.0.7 Core JDK 1.5 或更高 SLF4J 1.3.0 或更高 L ...
- Apache Mina原理及典型例子分析
Apache Mina ,一个高性能 Java 异步并发网络通讯框架.利用 Mina 可以高效地完成以下任务: TCP/IP 和 UDP/IP 通讯 串口通讯 VM 间的管道通讯 SSL/TLS JX ...
- 网络通信框架Apache MINA
Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...
- Apache Mina入门实例
一.mina是啥 ApacheMINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可扩展性的网络应用程序.它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的 ...
- Apache Mina -2
我们可以了解到 mina是个异步通信框架,一般使用场景是服务端开发,长连接.异步通信使用mina是及其方便的.不多说,看例子. 本次mina 使用的例子是使用maven构建的,过程中需要用到的jar包 ...
- Apache Mina UDP连接目标服务器地址时出现异常
俩种情形,第一种是开始连接时候就没连上服务器:第二种是服务器关闭连接,出现的异常: 第一种: java.lang.reflect.InvocationTargetException at sun.re ...
- Apache Mina入门
Mina第一次听到这个名称的时候,我以为是个MM的名字米娜,后来才知道… Apache MINA(Multipurpose Infrastructure for Network Application ...
随机推荐
- MTD应用学习札记【转】
转自:https://blog.csdn.net/lh2016rocky/article/details/70885421 今天做升级方案用到了mtd-utils中的flash_eraseall和fl ...
- thymeleaf:访问静态方法
<p class="left tel" th:if="${#strings.startsWith(T(net.common.util.tool.common.Req ...
- 支付宝:电脑网站沙箱测试(Java)
1.下载电脑网站的官方demo: 下载地址:https://docs.open.alipay.com/270/106291/ 2.下载解压导入eclipse readme.txt请好好看一下. 只有一 ...
- day25作业
1.阻塞 2.就绪 3.阻塞 4.Runnable 5.join() 6.synchronized 7.notify()和notifyAll() 8.Object 1.A 2.D ...
- Oracle ORA-12541:TNS:无监听程序
Oracle ORA-12541:TNS:无监听程序 标签: Oracle DataBase 今天使用Oracle数据库,使用可视化连接工具连接测试环境的数据库时提示无监听程序,最后在老师帮助下终于搞 ...
- vs 加载 dll 缓慢
https://jingyan.baidu.com/article/642c9d34e25cc2644b46f74b.html http://www.it610.com/article/2611781 ...
- (五)消费Dubbo服务
前面我们搞了发布Dubbo服务,发布的服务就是用来消费的,所以我们这里来调用服务,消费下: 创建maven项目 dubbo-demo-consumer pom.xml配置下: <dependen ...
- react 的JSX语法需要注意哪些点?
注释方式 ReactDOM.render( <div> {/*JSX 中的注释方式*/} </div>, document.getElementById('root') ) j ...
- C#小票打印机
使用的佳博GP-5890XIII http://www.cnblogs.com/lovenan/p/3217448.html using System; using System.Collection ...
- 000 关于IDEA的基本环境配置以及快速使用(git拉载程序,Jdk安装,tomcat部署,应用程序打包运行)
刚开始工作的时候,不熟悉,所以整理过这个文档. 一:导入git程序 1.准备 git链接 IDEA软件,最好是终极版 2.第一步选择从版本控制上选择git 3.拷贝源于目标地址 4.这时候根据引导进行 ...