MIna框架I/O Filter Chain层设计

I/O Filter Chain层是介于I/O Service层与I/O Handler层之间的一层,从它的命名上可以看出,这个层可以根据实际应用的需要,设置一组IoFilter来对I/O Service层与I/O Handler层之间传输数据进行过滤,任何需要在这两层之间进行处理的逻辑都可以放到IoFilter中。
我们看一下IoFilter的抽象层次设计,如图所示:
Mina_IoFilter
通过上述类图可见,要实现一个自定义的IoFilter,一般是直接实现IoFilterAdapter类。同时,Mina也给出了几类常用的开发IoFilter的实现类,如下所示:

  • LoggingFilter记录所有事件和请求
  • ProtocolCodecFilter将到来的ByteBuffer转换成消息对象(POJO)
  • CompressionFilter压缩数据
  • SSLFilter增加SSL – TLS – StartTLS支持

想要实现一个自定义的IoFilter实现类,只需要基于上述给出的几个实现类即可。
如果想要实现自己的IoFilter,可以参考如下例子:

public class MyFilter extends IoFilterAdapter {
	@Override
	public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
		// Some logic here...
		nextFilter.sessionOpened(session);
		// Some other logic here...
	}
}

下面通过一个例子来说明,如何使用IoFilter的实现类。

ProtocolCodecFilter
下面是Mina自带的例子,使用了ProtocolCodecFilter类:

package org.apache.mina.example.gettingstarted.timeserver;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer {
	/**
	 * We will use a port above 1024 to be able to launch the server with a
	 * standard user
	 */
	private static final int PORT = 9123;

	/**
	 * The server implementation. It's based on TCP, and uses a logging filter
	 * plus a text line decoder.
	 */
	public static void main(String[] args) throws IOException {
		// Create the acceptor
		IoAcceptor acceptor = new NioSocketAcceptor();

		// Add two filters : a logger and a codec
		acceptor.getFilterChain().addLast("logger", new LoggingFilter());
		acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));

		// Attach the business logic to the server
		acceptor.setHandler(new TimeServerHandler());

		// Configurate the buffer size and the iddle time
		acceptor.getSessionConfig().setReadBufferSize(2048);
		acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);

		// And bind !
		acceptor.bind(new InetSocketAddress(PORT));
	}
}

上面设置了两个IoFilter,关键是看如果基于文本行的消息,使用一个ProtocolCodecFilter包裹了一TextLineCodecFactory类的实例,使用起来非常容易。
构造一个ProtocolCodecFilter实例,需要实现一个ProtocolCodecFactory实例,一个ProtocolCodecFactory包含了对消息进行编解码(Codec)的逻辑,这样实现的好处是将编解码的逻辑和IoFilter解耦合。下面看一下类图:
Mina_IoFilter_ProtocolCodecFactory

LoggingFilter
如果需要记录通信过程中的事件以及请求,则可以直接使用LoggingFilter类,使用方法可以参考上面的例子。

CompressionFilter
CompressionFilter是与压缩/解压缩数据相关的IoFilter,我们可以看一下该类的构造方法,如下所示:

/**
     * Creates a new instance which compresses outboud data and decompresses
     * inbound data with default compression level.
     */
    public CompressionFilter() {
        this(true, true, COMPRESSION_DEFAULT);
    }

    /**
     * Creates a new instance which compresses outboud data and decompresses
     * inbound data with the specified <tt>compressionLevel</tt>.
     *
     * @param compressionLevel the level of compression to be used. Must
     */
    public CompressionFilter(final int compressionLevel) {
        this(true, true, compressionLevel);
    }

    /**
     * Creates a new instance.
     *
     * @param compressInbound <tt>true</tt> if data read is to be decompressed
     * @param compressOutbound <tt>true</tt> if data written is to be compressed
     * @param compressionLevel the level of compression to be used. Must
     */
    public CompressionFilter(final boolean compressInbound, final boolean compressOutbound, final int compressionLevel) {
        this.compressionLevel = compressionLevel;
        this.compressInbound = compressInbound;
        this.compressOutbound = compressOutbound;
    }

基本上就构造方法参数中指定的3个参数与压缩/解压缩相关:

  • compressionLevel
  • compressInbound
  • compressOutbound

使用的时候也比较简单,只需要创建一个CompressionFilter实例,加入到Filter Chain中即可。

DefaultIoFilterChainBuilder
Mina自带的DefaultIoFilterChainBuilder可以非常容易就可以构建一个Filter Chain,默认在创建IoAcceptor和IoConnector的时候,可以直接通过他们获取到一个DefaultIoFilterChainBuilder的实例,然后调用add*方法设置IoFilter链,如下面代码中示例:

          IoAcceptor acceptor = new NioSocketAcceptor();

          // Add two filters : a logger and a codec
          acceptor.getFilterChain().addLast("logger", new LoggingFilter());
          acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));

下面看一下来自Mina官网的表格,Mina框架也给出了一些典型的IoFilter的实现,引用如下所示:

Filter class Description
Blacklist BlacklistFilter Blocks connections from blacklisted remote addresses
Buffered Write BufferedWriteFilter Buffers outgoing requests like the BufferedOutputStream does
Compression CompressionFilter
ConnectionThrottle ConnectionThrottleFilter
ErrorGenerating ErrorGeneratingFilter
Executor ExecutorFilter
FileRegionWrite FileRegionWriteFilter
KeepAlive KeepAliveFilter
Logging LoggingFilter Logs event messages, like MessageReceived, MessageSent, SessionOpened, …
MDC Injection MdcInjectionFilter Inject key IoSession properties into the MDC
Noop NoopFilter A filter that does nothing. Useful for tests.
Profiler ProfilerTimerFilter Profile event messages, like MessageReceived, MessageSent, SessionOpened, …
ProtocolCodec ProtocolCodecFilter A filter in charge of encoding and decoding messages
Proxy ProxyFilter
Reference counting ReferenceCountingFilter Keeps track of the number of usages of this filter
RequestResponse RequestResponseFilter
SessionAttributeInitializing SessionAttributeInitializingFilter
StreamWrite StreamWriteFilter
SslFilter SslFilter
WriteRequest WriteRequestFilter

参考链接

Creative Commons License

本文基于署名-非商业性使用-相同方式共享 4.0许可协议发布,欢迎转载、使用、重新发布,但务必保留文章署名时延军(包含链接:http://shiyanjun.cn),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

评论(1): “MIna框架I/O Filter Chain层设计

欧阳平进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>