常用的网络通讯框架主要有:Mina ,Grizzly,Cindy,Netty 等,看了下cindy的代码,和mina有很多相似的地方,实现的比mina精简很多,据说性能还要好于mina.参照代码实现了一下 filterchain的HelloWorld版,简单说明一下cindy里对filterchain模式的应用.
首先定义filter接口,filter接口封装了session中的sessionStarted,sessionClosed,messageReceived等方法,为了简单,我只模拟一个send方法,用一个String的消息代替session对象
public interface Filter {
void send(FilterChain chain, String msg);
}
FilterChain是filter的一个管理容器,在cindy里filterChain管理2种filter,第一种是系统内部的filter,另外一种是用户定义的filter,看一下FilterChain的定义
public interface FilterChain {
public void addFilter(Filter filter);
public void send(String msg);
}
为了简单,我只定义了addFilter,而没有定义removeFilter方法,send方法其实是filterChain调用所管理的所有filter的一个方法,看一个具体实现
public abstract class AbstractFilterChain implements FilterChain {
protected static final Filter NULL_FILTER = new NullFilter();
protected static final Filter DISPACHER_FILTER = new FirstInnerFilter();
protected abstract Filter nextFilter();
public Filter next() {
Filter filter = nextFilter();
return filter != null ? filter : NULL_FILTER;
}
@Override
public void send(String msg) {
next().send(this, msg);
}
}
在这个抽象类里,我们基本可以看出filterChain是如何管理所有filter的,首先filterChain里定义了2个系统内部的 filter,FirstInnerFilter是filterChain里的第一个filter,在cindy里的名称是 DispacherFilter,里面是通过一个线程池DefaultDispacher调用所有的filter的,NullFilter是系统的最后一 个filter,当然我的实现是非常简单的,cindy实际上定义了很多个系统内部的filter,其中还有一个PacketDecoderFilter 用于解码的filter,主要处理字节流转换成java对象,类似netty 里的MessageReconizer
每次调用send,方法,都会通过nextFilter取得下一个filter进行调用,看一下最终实现
public class DefaultFilterChain extends AbstractFilterChain {
private Filter[] appFilters = new Filter[0];
private Filter dispacherFilter = DISPACHER_FILTER;
private int cursor = -1;
@Override
public void addFilter(Filter filter) {
Filter[] newFilters = new Filter[appFilters.length + 1];
if (appFilters.length > 0) {
System.arraycopy(appFilters, 0, newFilters, 0, appFilters.length);
}
newFilters[appFilters.length] = filter;
appFilters = newFilters;
}
@Override
protected Filter nextFilter() {
Filter filter = null;
if (dispacherFilter != null) {
filter = dispacherFilter;
dispacherFilter = null;
} else if (++cursor < appFilters.length) {
filter = appFilters[cursor];
} else {
filter = NULL_FILTER;
}
return filter;
}
}
addFilter比较好理解用于向chain容器内添加用户定义的filter
nextFilter是整个chain的调度中心,流程是:
首先调用系统内部的FirstInnerFilter,然后开始循环调用所有用户自定义的filter,最后是
系统内部的NullFilter,我们再看看各种filter的实现
public class FirstInnerFilter implements Filter {
@Override
public void send(FilterChain chain, String msg) {
System.out.println("first inner filter(Dispacher Filter): " + msg);
chain.send(msg);
}
}
FirstInnerFilter是容器里首个被调用的filter,在调用方法里,通过chain.send(msg),其实就是调用 FilterChain的 next().send(msg)方法,依此类推,遍历容器内所有的filter,下面是其他的实现:
public class NullFilter implements Filter {
@Override
public void send(FilterChain chain, String msg) {
System.out.println("the final of the chain, NullFilter: " + msg);
}
}
public class FilterAdapter implements Filter {
@Override
public void send(FilterChain chain, String msg) {
chain.send(msg);
}
}
所有的用户定义的filter继承自FilterAdapter,其实也可以不必这样的,可以直接在应用filter里调用chain.send(msg);
以下是两个用户自定义的filter示例
public class AppFilterA extends FilterAdapter {
@Override
public void send(FilterChain chain, String msg) {
System.out.println("AppFilterA: " + msg);
super.send(chain, msg);
}
}
public class AppFilterB extends FilterAdapter {
@Override
public void send(FilterChain chain, String msg) {
System.out.println("AppFilterB: " + msg);
super.send(chain, msg);
}
}
最后看一下测试代码:
public class TestChain {
public void send(String msg) {
DefaultFilterChain chain = new DefaultFilterChain();
chain.addFilter(new AppFilterA());
chain.addFilter(new AppFilterB());
chain.send(msg);
}
public static void main(String[] args) {
new TestChain().send("test msg");
}
}
cindy里的DefaultFilterChain是定义在AbstractSession里的一个内部类.
程序输出:
first inner filter(Dispacher Filter): test msg
AppFilterA: test msg
AppFilterB: test msg
the final of the chain, NullFilter: test msg
以上是一个超简单的模拟cindy里filterChain的一个实现,源码结构大体是这样,当然功能要丰富得多,支持倒序和正序两种chain的执行顺序等.