mina中责任链模式的实现
一、mina的框架回顾
责任链模式在mina中有重要的作用,其中Filter机制就是基于责任链实现的。

二、mina中filter
2.1、mina中的filterchain包结构

- IoFilter接口:Filter层的每个filter都是对上图IoFilter接口的实现。
- IoFilterChainBuilder接口和DefaultIoFilterChainBuilder实现不再细讲,从字面意思就是IoFilterChain的建造者。
- IoFilterEvent是代表filter事件,IoFilterLifeCycleException是指filter中出现循环链表异常。

三、mina的filter中实现类
3.0、NextFilter接口
NextFilter接口看上去和IoFilter接口差不多,但NextFilter接口代表的是“下一个filter”,这里的下是抽象的,因为在mina的各种链中,处理顺序有的是从头到尾,有的是从尾到头,而这里的下就代表了熟悉中的下一个filter。
3.1、HeadFilter
HeadFilter类只对发送消息处理方法重载,HeadFilter是发送消息最后的处理节点。
3.1.1、方法列表

3.1.2、调用IoService(边界)
关键代码见下面,将待发送的数据(字节)写到缓冲队列里,或直接调用flush()写到系统缓冲区。
WriteRequestQueue writeRequestQueue = s.getWriteRequestQueue();
if (!s.isWriteSuspended()) {
if (writeRequestQueue.size() == 0) {
// We can write directly the message
s.getProcessor().write(s, writeRequest);
} else {
s.getWriteRequestQueue().offer(s, writeRequest);
s.getProcessor().flush(s);
}
} else {
s.getWriteRequestQueue().offer(s, writeRequest);
}
3.1.1、全部源码
private class HeadFilter extends IoFilterAdapter {
@SuppressWarnings("unchecked")
@Override
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
// Maintain counters.
if (writeRequest.getMessage() instanceof IoBuffer) {
IoBuffer buffer = (IoBuffer) writeRequest.getMessage();
// I/O processor implementation will call buffer.reset()
// it after the write operation is finished, because
// the buffer will be specified with messageSent event.
buffer.mark();
int remaining = buffer.remaining();
if (remaining == 0) {
// Zero-sized buffer means the internal message
// delimiter.
s.increaseScheduledWriteMessages();
} else {
s.increaseScheduledWriteBytes(remaining);
}
} else {
s.increaseScheduledWriteMessages();
}
WriteRequestQueue writeRequestQueue = s.getWriteRequestQueue();
if (!s.isWriteSuspended()) {
if (writeRequestQueue.size() == 0) {
// We can write directly the message
s.getProcessor().write(s, writeRequest);
} else {
s.getWriteRequestQueue().offer(s, writeRequest);
s.getProcessor().flush(s);
}
} else {
s.getWriteRequestQueue().offer(s, writeRequest);
}
}
@SuppressWarnings("unchecked")
@Override
public void filterClose(NextFilter nextFilter, IoSession session) throws Exception {
((AbstractIoSession) session).getProcessor().remove(session);
}
}
3.2、TailFilter
TailFilter类只对接受消息处理方法重载。
3.2.1、方法列表

3.2.2、调用IoHandler(边界)
先判断待处理数据类型,如果不满足条件则继续读取数据。否则,调用handler类来接收处理消息。
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);
}
}
}
3.2.3、全部源码
private static class TailFilter extends IoFilterAdapter {
@Override
public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
try {
session.getHandler().sessionCreated(session);
} finally {
// Notify the related future.
ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE);
if (future != null) {
future.setSession(session);
}
}
}
@Override
public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
session.getHandler().sessionOpened(session);
}
@Override
public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
try {
s.getHandler().sessionClosed(session);
} finally {
try {
s.getWriteRequestQueue().dispose(session);
} finally {
try {
s.getAttributeMap().dispose(session);
} finally {
try {
// Remove all filters.
session.getFilterChain().clear();
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerClosedReadFuture();
}
}
}
}
}
}
@Override
public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
session.getHandler().sessionIdle(session, status);
}
@Override
public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
try {
s.getHandler().exceptionCaught(s, cause);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerFailedReadFuture(cause);
}
}
}
@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 {
session.getHandler().messageReceived(s, message);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerReadFuture(message);
}
}
}
@Override
public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
session.getHandler().messageSent(session, writeRequest.getMessage());
}
@Override
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
nextFilter.filterWrite(session, writeRequest);
}
@Override
public void filterClose(NextFilter nextFilter, IoSession session) throws Exception {
nextFilter.filterClose(session);
}
}
3.3、Entry接口

Entry接口是IoFilterChain接口的一个内部接口,Entry是对IoFilter和NextFilter的封装整合接口,它属于链表IoFilterChain中的元素。指向当前和下一个过滤器。其中IoFilterChain接口代表了过滤器的容器,它本身就是一个对象引用形成的链表结构,默认的实现DefaultIoFilterChain其实有对链表头(head)的引用,找到头后就可以顺着头向下找,一直找到尾(tail)。
Entry接口与IoFilterChain接口关系如下:

3.4、EntryImpl类
EntryImpl是Entry接口的实现类,类的成员中含两个接口,filter和nextFilter,他们所用的接口是不一样的,至于为什么不用同一个接口,我想可能是因为接口职责单一的原则吧。
从EntryImpl类的构造方法看到,EntryImpl中保持对上一个节点和下一个节点引用,双向链表结构,name即过滤层名称,filter即过滤层的具体实现,而nextFilter是在构造方法中的内部实现。
private class EntryImpl implements Entry {
private EntryImpl prevEntry;
private EntryImpl nextEntry;
private final String name;
private IoFilter filter;
private final NextFilter nextFilter;
3.4.2、IoFilter接口和NextFilter接口:
虽然有IoFilter和NextFilter两个接口,接口方法都差不多,但最后真正业务的执行者还是IoFilter的实现,
IoFilter:IoFilterAdapter做为它的默认实现,完成了适配器的功能,以后的类可以直接继承它而不用实现IoFilter接口,想实现哪个方法只需要覆盖IoFilterAdapter的类的方法即可。
NextFilter:只起到转发的作用,看EntryImpl中的匿名的NextFilter实现类中,基本每个方法都是调用callNextSessionIdle()来完成转发的。
3.4.3、全部源码
private class EntryImpl implements Entry {
private EntryImpl prevEntry;
private EntryImpl nextEntry;
private final String name;
private IoFilter filter;
private final NextFilter nextFilter;
private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) {
if (filter == null) {
throw new IllegalArgumentException("filter");
}
if (name == null) {
throw new IllegalArgumentException("name");
}
this.prevEntry = prevEntry;
this.nextEntry = nextEntry;
this.name = name;
this.filter = filter;
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);
}
public String toString() {
return EntryImpl.this.nextEntry.name;
}
};
}public void addAfter(String name, IoFilter filter) {
DefaultIoFilterChain.this.addAfter(getName(), name, filter);
}
public void addBefore(String name, IoFilter filter) {
DefaultIoFilterChain.this.addBefore(getName(), name, filter);
}
public void remove() {
DefaultIoFilterChain.this.remove(getName());
}
public void replace(IoFilter newFilter) {
DefaultIoFilterChain.this.replace(getName(), newFilter);
}
}
3.5、IoFilterEvent

public class IoEvent implements Runnable {
private final IoEventType type;
private final IoSession session;
private final Object parameter;
public IoEvent(IoEventType type, IoSession session, Object parameter) {
if (type == null) {
throw new IllegalArgumentException("type");
}
if (session == null) {
throw new IllegalArgumentException("session");
}
this.type = type;
this.session = session;
this.parameter = parameter;
}
public void run() {
fire();
}
public void fire() {
switch (getType()) {
case MESSAGE_RECEIVED:
getSession().getFilterChain().fireMessageReceived(getParameter());
break;
case MESSAGE_SENT:
getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter());
break;
case WRITE:
getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter());
break;
case CLOSE:
getSession().getFilterChain().fireFilterClose();
break;
case EXCEPTION_CAUGHT:
getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter());
break;
case SESSION_IDLE:
getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter());
break;
case SESSION_OPENED:
getSession().getFilterChain().fireSessionOpened();
break;
case SESSION_CREATED:
getSession().getFilterChain().fireSessionCreated();
break;
case SESSION_CLOSED:
getSession().getFilterChain().fireSessionClosed();
break;
default:
throw new IllegalArgumentException("Unknown event type: " + getType());
}
}
}
IoFilterEvent 实现类
public class IoFilterEvent extends IoEvent {
/** A logger for this class */
static Logger LOGGER = LoggerFactory.getLogger(IoFilterEvent.class);
/** A speedup for logs */
static boolean DEBUG = LOGGER.isDebugEnabled();
private final NextFilter nextFilter;
public IoFilterEvent(NextFilter nextFilter, IoEventType type, IoSession session, Object parameter) {
super(type, session, parameter);
if (nextFilter == null) {
throw new IllegalArgumentException("nextFilter must not be null");
}
this.nextFilter = nextFilter;
}
public NextFilter getNextFilter() {
return nextFilter;
}
@Override
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;
case MESSAGE_SENT:
WriteRequest writeRequest = (WriteRequest) getParameter();
nextFilter.messageSent(session, writeRequest);
break;
case WRITE:
writeRequest = (WriteRequest) getParameter();
nextFilter.filterWrite(session, writeRequest);
break;
case CLOSE:
nextFilter.filterClose(session);
break;
case EXCEPTION_CAUGHT:
Throwable throwable = (Throwable) getParameter();
nextFilter.exceptionCaught(session, throwable);
break;
case SESSION_IDLE:
nextFilter.sessionIdle(session, (IdleStatus) getParameter());
break;
case SESSION_OPENED:
nextFilter.sessionOpened(session);
break;
case SESSION_CREATED:
nextFilter.sessionCreated(session);
break;
case SESSION_CLOSED:
nextFilter.sessionClosed(session);
break;
default:
throw new IllegalArgumentException("Unknown event type: " + type);
}
}
}
3.6、IoFilterLifeCycleException
mina中有3处使用了它,
mina中责任链模式的实现的更多相关文章
- es6 class中责任链模式与AOP结合
责任链模式大家应该都清楚,比如JS中的冒泡,Java中的拦截器.过滤器,都运用到了责任链模式. 可以看我之前的文章介绍责任链的:https://www.cnblogs.com/wuguanglin/p ...
- Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理
原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...
- C#设计模式-责任链模式
在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在面试的 ...
- C#设计模式(21)——责任链模式
一.引言 在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所 ...
- 设计模式学习之责任链模式(Chain of Responsibility,行为型模式)(22)
参考:http://www.cnblogs.com/zhili/p/ChainOfResponsibity.html 一.引言 在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1 ...
- Java设计模式13:责任链模式
前言 来菜鸟这个大家庭10个月了,总得来说比较融入了环境,同时在忙碌的工作中也深感技术积累不够,在优秀的人身边工作必须更加花时间去提升自己的技术能力.技术视野,所以开一个系列文章,标题就轻松一点叫做最 ...
- 责任链模式的使用-Netty ChannelPipeline和Mina IoFilterChain分析
本文来自网易云社区 作者:乔安然 1. Chain of Responsiblity 定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链 ...
- [工作中的设计模式]责任链模式chain
一.模式解析 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...
- java设计模式之责任链模式以及在java中作用
责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...
随机推荐
- scjp考试准备 - 8 - final关键字
题目,如下代码的执行结果: import java.util.ArrayList; class Pizza{ ArrayList toppings; public final void addTopp ...
- QTabWidget和QtabBar的区别
切换标签tab 是QTabBar int QTabWidget::insertTab ( int index, QWidget * page, const QString & label ) ...
- 图片qq浏览器不显示,微信显示问题原因
1.qq浏览器关闭云加速就可以了
- Selenium with Python 008 - WebDriver 元素等待
如今大多数Web应用程序使用Ajax技术,当浏览器在加载页面时,页面上的元素可能并不是同时被加载完成的,这给元素的定位增加了困难.如果因为在加载某个元素时延迟而造成ElementNotVisibleE ...
- C++构造函数知识点整理(C++11标准)
引言 构造函数是c++中的一个比较难的语法知识点.编程实践中,由于在很多情况下可以不显示定义构造函数,或者,虽然定义构造函数的方式并不十分适当,但是程序也能正常运行,故而并不是特别引起开发者的重视. ...
- sizeof结构体
规则1:结构体的对折长度为其基本数据成员的长度的最大值. 规则2:指定边界情况下,结构体的对折长度为自身对折长度和指定对折长度中较小者. 规则3:当行内结构体的基本数据成员的起始地址必须为其长度的整数 ...
- Python中threading模块的join函数
Join的作用是阻塞进程直到线程执行完毕.通用的做法是我们启动一批线程,最后join这些线程结束,例如: for i in range(10): t = ThreadTest(i) thread_ar ...
- S3C2440启动方式
不管S3C2440的启动设备是什么,它都是从0x0000 0000地址开始执行程序的,所不同的是地址的映射不一样.基于S3C2440的嵌入式系统上电之后,需要首选选择启动设备,2440的启动方式选择是 ...
- TCP中的服务端与客户端的实现
TCP中首先要在服务端开启监听,这样才可以从客户端链接 using System; using System.Collections.Generic; using System.Linq; using ...
- 转载:将STM32的标准库编译成lib使用【图文】
from:http://www.cnblogs.com/zyqgold/p/3189719.html 百度上边也有不少关于lib文件的文章,恰巧看到该博文,感觉该博文的条理清晰,步骤明确,故复制到这个 ...