Mina IoFilter注意事项说明

原文地址:Mina过滤器(Mina user guide Chapter5 Filter)

IoFilter是Mina核心结构提供的一个很重要的角色。它过滤了所有在IoService和IoHandler之间的I
/ O事件和请求。如果你有一个使用web应用程序编程的经验,你可以放心地认为这是一个类似的Servlet过滤器。Mina提供了许多开箱即用的过滤器加速网络应用程序开发的速度,通过简化使用开箱即用过滤器等典型的横切关注点:

  • · LoggingFilter 日志揭露所有的事件和请求.
  • · ProtocolCodecFilter 从ByteBuffe转化为消息对应的POJO
  • · CompressionFilter 压缩所有数据.
  • · SSLFilter adds SSL - TLS - StartTLS support.安全过滤器
  • · 可以自己实现更多的过滤器

在本教程中,我们将介绍如何实现一个现实世界的IoFilter用例。一般很容易实现一个IoFilter,但你可能还需要知道Mina内部的细节。任何相关的内部属性将被解释。

1.1.1. 已经存在的过滤器

我们已经创建了许多的过滤器,下面用表格列举一下已经存在的过滤器,并附上简单的使用说明:


Filter


class


描述


Blacklist


BlacklistFilter


块连接远程地址黑名单过滤器


Buffered Write


BufferedWriteFilter


用BufferedOutputStream做缓冲输出请求


Compression


CompressionFilter


ConnectionThrottle


ConnectionThrottleFilter


ErrorGenerating


ErrorGeneratingFilter


Executor


ExecutorFilter


FileRegionWrite


FileRegionWriteFilter


KeepAlive


KeepAliveFilter


Logging


LoggingFilter


日志记录事件消息,如:MessageReceived,MessageSent,

SessionOpened,


MDC Injection


MdcInjectionFilter


将IoSession 属性注入MDC


Noop


NoopFilter


一个什么也不做的过滤器,只对测试有用


Profiler


ProfilerTimerFilter


剖析事件消息,如: MessageReceived, MessageSent, SessionOpened, ...


ProtocolCodec


ProtocolCodecFilter


编解码过滤器


Proxy


ProxyFilter


Reference counting


ReferenceCountingFilter


跟踪数字用法的过滤器


RequestResponse


RequestResponseFilter


SessionAttributeInitializing


SessionAttributeInitializingFilter


StreamWrite


StreamWriteFilter


SslFilter


SslFilter


WriteRequest


WriteRequestFilter

1.1.2. 可选事件的重载

您可以扩展IoAdapter代替直接实现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...

    }}

1.1.3. 转换一个写入请求

如果你要通过IoSession.write()改变传入写请求,事情可能会变得很棘手。例如,让我们假设你的过滤器会从HighLevelMessage到 LowLevelMessage进行过滤,IoSession.write()被 HighLevelMessage对象所调用。你可以插入适当的转换代码过滤的filterWrite()方法,并认为这样就够了。然而,你必须注意,您还需要照顾messageSent事件,因为IoHandler或任何过滤器接下来会期望messageSent()将HighLevelMessage作为方法的参数。由于它是非理性的,当调用者HighLevelMessage准备通知LowLevelMessage,实际上LowLevelMessage已发送完成。因此,如果你的过滤器执行转换,你必须实现filterWrite()和messageSent()。

仍需注意,您还需要执行类似的机制,即使输入和输出对象的类型是相同的(例如CompressionFilter)。因为IoSession.write()的调用者将期望他通过messageSent()写入到对应的handler方法。

假设你正在实施一个过滤器,将一个字符串转换为一个char[]。你的过滤器filterWrite()将看起来像下面的:

public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest request) {

    nextFilter.filterWrite(

        session, new DefaultWriteRequest(

                ((String) request.getMessage()).toCharArray(), request.getFuture(), request.getDestination()));
}

现在,我们需要在messageSent()方法中做反转:

public void messageSent(NextFilter nextFilter, IoSession session, Object message) {

    nextFilter.messageSent(session, new String((char[]) message));
}

String-to-ByteBuffer转换呢?我们可以更有效率,因为我们不需要重建原始消息(字符串)。然而,这是比之前更复杂的例子:

public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest request) {

    String m = (String) request.getMessage();

    ByteBuffer newBuffer = new MyByteBuffer(m, ByteBuffer.wrap(m.getBytes());

    nextFilter.filterWrite(

            session, new WriteRequest(newBuffer, request.getFuture(), request.getDestination()));}

public void messageSent(NextFilter nextFilter, IoSession session, Object message) {

    if (message instanceof MyByteBuffer) {

        nextFilter.messageSent(session, ((MyByteBuffer) message).originalValue);

    } else {

        nextFilter.messageSent(session, message);

    }}

private static class MyByteBuffer extends ByteBufferProxy {

    private final Object originalValue;

    private MyByteBuffer(Object originalValue, ByteBuffer encodedValue) {

        super(encodedValue);

        this.originalValue = originalValue;

    }}

如果您使用的是Mina2.0,他与1.0和1.1有些不同。请同时参考CompressionFilterRequestResponseFilter

1.1.4. 当心过滤器sessionCreated事件

sessionCreated是一个特殊的事件,必须在I / O处理器线程中执行(参见配置线程模型)。sessionCreated从不转发事件给其他线程。

public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {

    // ...

    nextFilter.sessionCreated(session);}

// DON'T DO THIS!public void sessionCreated(final NextFilter nextFilter, final IoSession session) throws Exception {

    Executor executor = ...;

    executor.execute(new Runnable() {

        nextFilter.sessionCreated(session);

        });

    }

1.1.5. 注意空的Buffers缓冲区

Mina使用空缓冲区作为一个内部信号的情况。空缓冲区有时会成为一个问题,因为它会导致IndexOutOfBoundsException等各种异常。本节解释如何避免这种难以预料的情况。

ProtocolCodecFilter(编解码过滤器)使用一个空缓冲区(即buf.hasRemaining()= 0)标记消息结尾。如果你的过滤器放置在ProtocolCodecFilter之前,请确保你的过滤器处理空缓冲区。如果缓冲区为空,你的下一个过滤器过滤实现可能会抛出一个意想不到的异常:

public void messageSent(NextFilter nextFilter, IoSession session, Object message) {

    if (message instanceof ByteBuffer && !((ByteBuffer) message).hasRemaining()) {

        nextFilter.messageSent(nextFilter, session, message);

        return;

    }

    ...}

public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest request) {

    Object message = request.getMessage();

    if (message instanceof ByteBuffer && !((ByteBuffer) message).hasRemaining()) {

        nextFilter.filterWrite(nextFilter, session, request);

        return;

    }

    ...}

我们总是要为每个过滤器插入if块吗?幸运的是,你不需要。处理空缓冲区的黄金法则:

  • 如果你的过滤器工作没有任何问题,即使缓冲区为空,不需要添加if块。 
  • 如果你的过滤器放置ProtocolCodecFilter之后,你不需要添加if块。
  • 否则,你需要添加if块。

如果你需要if块,请记住你不总是需要遵循上面的例子。您可以检查是否缓冲区为空,无论你想怎样都行,只要你的过滤器不抛出一个意想不到的异常。

时间: 2024-10-13 03:13:27

Mina IoFilter注意事项说明的相关文章

(三)Mina源码解析之IoFilter

本篇文章主要剖析Mina中的过滤器是如何实现的 首先还是引入一个简单的完整的server端的例子,代码如下 public class Server { public static void main(String[] args) { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getSessionConfig().setReadBufferSize(2048); acceptor.getSessionConfig().setId

mina框架详解

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型.Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并

MINA框架初探

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型.Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并

Apache Mina

初步接触RPC通信框架,目前有很多优秀的RPC框架,今天我参考该博文:http://www.cnblogs.com/xuekyo/archive/2013/03/06/2945826.html 学习了Aapche Mina通信框架.博主介绍的非常详细,包括Mina的源码流程,这里通过阅读博主的文章进行了学习记录,方便以后需要时使用. Apache Mina 是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可扩展性的网络应用程序.它提供了一个通过Java NIO在不同的传输例如TCP/IP

MINA学习汇总

MINA学习汇总 Apache Mina Server 是一个网络通信应用框架,用于开发高性能和高可用性的网络应用程序.它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型. Apache Mina简单理解它是一个封装底层IO操作,提供高级操作API的通讯框架! Mina在整个网通通信结构中位置: Mina处于中间

MINA框架

MINA 框架简介 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型.Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么

大并发量socket 通信框架MINA介绍

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架.当前发行的 MINA 版本支持基于 Java NIO 技术的TCP/UDP 应用程序开发.串口通讯程序. Mina 的应用层: 一个设计成熟的开源框架,总是会仅可能的减少侵入性,并在整个项目中找到合适的位置,而不应对整个项目的构架设计产生过多的影响,图 1 就是 MIN

NIO框架之MINA源码解析(三):底层通信与责任链模式应用

本文主要介绍下在mina中责任链模式的应用以及mina对于数据读写的处理. 在mina中,对数据的读操作是在processor类里面触发的,收到新消息后就触发读数据链去处理新消息直到自己的业务逻辑代码(IoHandler). 在mina中,数据的写(write)和发(send)差别相对较大,mina中的写消息最终的结果只是把要写的消息经过写数据链处理后的最终结果放在了一个缓存中,并把当前session标记为可发. 数据的发送就是传统中我们所说的发消息,就是把写消息最终处理的结果发送到客户端,待发

网络通信框架Apache MINA

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架.当前发行的 MINA 版本支持基于 Java NIO 技术的TCP/UDP 应用程序开发.串口通讯程序. Mina 的应用层: 一个设计成熟的开源框架,总是会仅可能的减少侵入性,并在整个项目中找到合适的位置,而不应对整个项目的构架设计产生过多的影响,图 1 就是 MIN