Mina最主要的工作就是把底层传输的字节码转换为Java对象,提供给应用程序;或者把应用程序返回的结果转换为字节码,交给底层传输。完成转换功能,则需要相应的编解码器,这些都是由IoFilter完成的,因此IoFilter是Mina的精髓所在。
Filter,过滤器的意思。IoFilter,I/O操作的过滤器。IoFilter和Servlet中的过滤器一样,主要用于拦截和过滤网络传输中I/O操作的各种消息,是在应用层和我们业务员层之间的过滤层。在Mina 的官方文档中已经提到了IoFilter 的作用:
(1)记录事件的日志(Mina默认提供了LoggingFilter)
(2)测量系统性能
(3)信息验证
(4)过载控制
(5)信息的转换(主要就是编码和解码)
(6)和其他更多的信息
IoService实例会绑定一个DefaultIoFilterChainBuilder---- 过滤器链,我们把自定义的各种过滤器(IoFilter)自由的插放在这个过滤器链上了,类似于一种可插拔的功能!
类结构图
常用接口为:IoFilter,IoFilterChainBuilder
常用类为:IoFilterAdapter,DefaultIoFilterChainBuilder,ProtocolCodecFilter,LoggingFilter
分析:
IoFilter有2个实现类:
IoFilterAdapter是个抽象的适配器类,我们可以根据需要扩展这个类,并且有选择的覆盖过滤器的方法(自定义过滤器);所有方法的默认把事件转发到下一个过滤器;
ReferenceCountingFilter封装了IoFilter实例,监看调用该filter的对象的个数,如果没有任何对象调用该IoFilter,就自动销毁IoFilter;
编写自定义IoFilter,继承IoFilterAdapter,有选择的覆盖过滤器的方法:
/*
自定义客户端过滤器
*/
public class MyClientFilter extends IoFilterAdapter {
private static final Logger logger = LogManager.getLogger(MyClientFilter.class);
@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
logger.info("ClientFilter接收到客户端消息:" + message);
// 传给下一个过滤器
nextFilter.messageReceived(session, message);
}
@Override
public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
logger.info("ClientFilter接收到服务端消息:" + writeRequest.getMessage());
// 传给下一个过滤器
nextFilter.messageSent(session, writeRequest);
}
}
在程序中添加自定义IoFilter
在handler处理之前,会调用相应的过滤器进行过滤(不区分接收或者发送),添加了自定义的过滤器后,也会经过我们自定义的过滤器后,才会交给handler进行处理。
在FilterChain中都是addLast()的方式添加在过滤链的最后面,这时候,把那个过滤器放在前面,就会先执行那个过滤器!
同addLast()方法一样,还提供了addFirst(),addBefore()等方法供使用。此时,就不难知道如何添加过滤器了吧!它们的顺序如何,就看你的设置的位置了!
日志过滤器是根据IoSession的状态(创建、开启、发送、接收、异常等等)来记录会话的事件信息的!这对我们跟踪IoSession很有用。当地,也可以自定义logger的日志级别,定义记录那些状态的日志。比如:
// 设置日志过滤器
LoggingFilter lf=new LoggingFilter();
lf.setMessageReceivedLogLevel(LogLevel.DEBUG);
acceptor.getFilterChain().addLast("logger",lf);
待续。