I/O Filter Chain层是介于I/O Service层与I/O Handler层之间的一层,从它的命名上可以看出,这个层可以根据实际应用的需要,设置一组IoFilter来对I/O Service层与I/O Handler层之间传输数据进行过滤,任何需要在这两层之间进行处理的逻辑都可以放到IoFilter中。
我们看一下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解耦合。下面看一下类图:
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 |
参考链接
- http://mina.apache.org/mina-project/userguide/ch5-filters/ch5-filters.html
- http://mina.apache.org/mina-project/userguide/ch9-codec-filter/ch9-codec-filter.html
- http://mina.apache.org/mina-project/userguide/ch10-executor-filter/ch10-executor-filter.html
- http://mina.apache.org/mina-project/userguide/ch11-ssl-filter/ch11-ssl-filter.html
- http://mina.apache.org/mina-project/userguide/ch12-logging-filter/ch12-logging-filter.html
本文基于署名-非商业性使用-相同方式共享 4.0许可协议发布,欢迎转载、使用、重新发布,但务必保留文章署名时延军(包含链接:http://shiyanjun.cn),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
简单之美,非常棒!