总有那么一群人,他们默默无闻的工作在自己的岗位上,你永远都接触不到他们,可是离了他们完整的做好一件事。譬如只注意在荧光屏上的明星,却不知道谁给他们打得灯光、谁给他们踩得位、谁给他们化妆端茶送水等等。IoFilter也是这群人中的一员,每个session的请求和事件离不了他们,IoFilter在IoService和IoHandler之间提供了各个层面的切面支持,让其他两个组件安心做自己的事而不用关注其他细节。软件工程的魅力也在于此——解耦。
Filter | class | Description |
---|---|---|
Blacklist | BlacklistFilter | 黑名单过滤器 |
BufferedWrite | BufferedWriteFilter | 发送缓存过滤器,缓存发送的消息,避免短小消息频繁发送 |
Compression | CompressionFilter | 数据压缩过滤器 |
ConnectionThrottle | ConnectionThrottleFilter | 连接控制过滤器,对同一IP地址频繁的创建连接的时间间隔进行控制 |
ErrorGenerating | ErrorGeneratingFilter | 花数据过滤器,增加、修改、移除接受的数据包内容,可作为加密的方式 |
Executor | ExecutorFilter | 处理线程池过滤器,让每个请求或者事件都通过线程池去执行 |
FileRegionWrite | FileRegionWriteFilter | 文件转换过滤器,通常应该由IoProcess做这件事,但若需要压缩或者修改时, 可通过过滤器链之间的配合来实现 |
KeepAlive | KeepAliveFilter | 心跳包过滤器,在idle状态时发送心跳包,并能对超时进行处理 |
Logging | LoggingFilter | 日志记录过滤器,最常用之一 |
MDC Injection | MdcInjectionFilter | 日志信息注入过滤器,MDC(Mapped Diagnostic Context有译作线程映射表)是日志 框架维护的一组信息键值对,可向日志输出信息中插入一些想要显示的内容。 |
Noop | NoopFilter | 用作内部测试的filter,什么也没做 |
Profiler | ProfilerTimerFilter | 时间分析过滤器,记录各种事件消耗的时间 |
ProtocolCodec | ProtocolCodecFilter | 编解码过滤器,最常用之二 |
Proxy | ProxyFilter | 是IoConnector在连接握手时自动加入的过滤器,握手成功后就透明了 |
Reference counting | ReferenceCountingFilter | 引用数过滤器,能记录该过滤器被加入或移除过滤器链的次数,真实使用 是继承他。 |
RequestResponse | RequestResponseFilter | 继承WriteRequest |
SessionAttributeInitializing | SessionAttributeInitializingFilter | 初始化过滤器 |
StreamWrite | StreamWriteFilter | InputStream直接转换成IoBuffer的过滤器 |
SslFilter | SslFilter | TCP/IP层面的SSl加解密过滤器 |
WriteRequest | WriteRequestFilter | 简化IoFilter IoEventType.WRITE事件的实现的抽象过滤器 |
public final void remove(S session) {
scheduleRemove(session);
startupProcessor();
}
private void scheduleRemove(S session) {
removingSessions.add(session);
}
当IoProcessor工作线程执行一个循环,调用removeSessions()方法,状态为SessionState.OPENED的session将被移除,移除的代码中就包括刷新消息队列,其中代码如下,从而引发一次过滤器链的调用。
if (message instanceof IoBuffer) {
IoBuffer buf = (IoBuffer) message;
if (buf.hasRemaining()) {
buf.reset();
failedRequests.add(req);
} else {
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireMessageSent(req);
}
} else {
failedRequests.add(req);
}
最终调用的是TailFilter,他的代码如下:
private static class TailFilter extends IoFilterAdapter {
public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
session.getHandler().sessionCreated(session);
}
public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
session.getHandler().sessionOpened(session);
}
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();
}
}
}
}
}
}
public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
session.getHandler().sessionIdle(session, status);
}
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);
}
}
}
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
session.getHandler().messageReceived(s, message);
}
public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
session.getHandler().messageSent(session, writeRequest.getMessage());
}
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
nextFilter.filterWrite(session, writeRequest);
}
public void filterClose(NextFilter nextFilter, IoSession session) throws Exception {
nextFilter.filterClose(session);
}
}
AbstractIoSession.write(Object message) {
...
IoFilterChain filterChain = getFilterChain();
filterChain.fireFilterWrite(writeRequest);
...
}
DefaultIoFilterChain.fireFilterWrite(WriteRequest writeRequest) {
Entry tail = this.tail;
callPreviousFilterWrite(tail, session, writeRequest);
}
触发逆序的过滤器链,最终到HeadFilter中:
...其他Filter
HeadFilter.filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
...
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);
}
}
IoServiceListener listener = new IoServiceListener() {
public void sessionDestroyed(IoSession session) throws Exception {
}
public void sessionCreated(IoSession session) throws Exception {
}
public void serviceIdle(IoService service, IdleStatus idleStatus)
throws Exception {
}
public void serviceDeactivated(IoService service) throws Exception {
}
public void serviceActivated(IoService service) throws Exception {
}
};
acceptor.addListener(listener);
acceptor.removeListener(listener);
public interface IoFutureListener extends EventListener {
void operationComplete(F future);
}
因为大部分的future都被mina集成在框架里,所以future的listener支持一项特性:若任务已经执行完后添加的listener将被立刻执行。我们先看看future是怎么实现该功能的。
public IoFuture addListener(IoFutureListener> listener) {
if (listener == null) {
throw new IllegalArgumentException("listener");
}
boolean notifyNow = false;
synchronized (lock) {
if (ready) {
notifyNow = true;
} else {
if (firstListener == null) {
firstListener = listener;
} else {
if (otherListeners == null) {
otherListeners = new ArrayList>(1);
}
otherListeners.add(listener);
}
}
}
//就是这里了!如果ready完成了,则马上执行
if (notifyNow) {
notifyListener(listener);
}
return this;
}
那不用说就知道啦,在notiffyListener中将会回调监听器的方法。