`
bsr1983
  • 浏览: 1116035 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MINA学习笔记五——第五章 Filters 过滤器

    博客分类:
  • Mina
 
阅读更多

第五章 Filters——过滤器

IoFilterMINA的核心结构之一,在MINA中扮演一个非常重要的角色。它过滤IoServiceIoHandler之间的所有I/O事件和请求。如果你有web应用程序的编程经验,你可以把它看做是servlet过滤器的同胞兄弟。我们提供了很多开箱即用的过滤器,通过简化在一些典型的关注点上使用这些开箱即用的过滤器来加快网络应用程序开发的步伐。

1LoggingFilter:日志过滤器记录所有的事件和请求。

2ProtocolCodecFilter:协议编码过滤器,在输入的ByteBuffer转换及消息对象间做相互转换

3CompressionFilter:压缩过滤器,压缩所有数据

4SSLFilter:SSL过滤器,添加SSL - TLS – StartTLS支持

还有很多其他的过滤器。

在这个教程中,我们将展示在实际的应用场景中一个IoFilter是多么重要。通常实现一个IoFilter是很简单的,但你也可能需要了解MINA内部实现的细节。所有这些内部属性都将在这里做统一说明。

4.1现存的过滤器

我们有一些已经写好的过滤器,下表是所有现存的过滤器清单,包含个过滤器用法的简短描述。

过滤器名称

对应类

描述

Blacklist

BlacklistFilter

阻止在黑名单中的远程地址的连接

Buffered Write

BufferedWriteFilter

BufferedOutputStream类似,实现外发请求缓存

Compression

CompressionFilter

 

ConnectionThrottle

ConnectionThrottleFilter

 

ErrorGenerating

ErrorGeneratingFilter

 

Executor

ExecutorFilter

 

FileRegionWrite

FileRegionWriteFilter

 

KeepAlive

KeepAliveFilter

 

Logging

LoggingFilter

记录所有消息事件,像收到消息,发出消息,打开会话...

MDC Injection

MdcInjectionFilter

多描述编码(MDCMultiple Description Coding)中注入IoSessionkey属性

Noop

NoopFilter

一个不做任何事情的过滤器,在测试时是非常有用的

Profiler

ProfilerTimerFilter

针对消息事件的用户配置过滤器

ProtocolCodec

ProtocolCodecFilter

一个负责消息编码、解码的过滤器

Proxy

ProxyFilter

 

Reference counting

ReferenceCountingFilter

跟踪使用这个过滤器的数量

RequestResponse

RequestResponseFilter

 

SessionAttributeInitializing

SessionAttributeInitializingFilter

 

StreamWrite

StreamWriteFilter

 

SslFilter

SslFilter

 

WriteRequest

WriteRequestFilter

 

4.2 选择性地覆盖事件

你可以通过继承IoAdapter而不是直接实现IoFilter来定义自己的过滤器。除非覆盖对应的事件方法,否则所有接收到的请求都将被立即发送给下一个过滤器。

publicclassMyFilterextends IoFilterAdapter {

    @Override

    publicvoidsessionOpened(NextFilter nextFilter, IoSession session)throws Exception {

        // Some logic here...

        nextFilter.sessionOpened(session);

        // Some other logic here...

    }

}

4.3转换一个写请求

如果你想转换一个通过IoSession.write()传入的写请求,事情会非常棘手。例如,我们假定你的过滤器要把调用IoSession.write()中的 HighLevelMessage对象转换为LowLevelMessage对象。你可能认为只要在你的过滤器的filterWrite()方法中插入适当的转换代码就够了,但是,不得不注意一点是你也需要考虑messageSent事件,因为一个IoHandler或后续的任何过滤器都希望将HighLevelMessage对象作为参数调用其messageSent()方法。当被调用的方法实际写入的是HighLevelMessage,却被告知发送的是LowLevelMessage对象,这是不合理的。因此,如果你的过滤器要进行转换操作,你就必须同时实现filterWrite()messageSent()这两个方法。

还需要注意的一点是,即便是输入和输出的对象(例如:CompressionFilters)是完全相同的你也要采取类似的机制。因为这正是IoSession.write()的调用者所期望你写入到它的处理器方法messageSent()中的。

假定你要实现一个将String转换到一个char[]的过滤器,那么你的过滤器的filterWrite()方法看起来将是下面这个样子。

publicvoidfilterWrite(NextFilter nextFilter, IoSession session, WriteRequest request)

{

    nextFilter.filterWrite(

        session,new DefaultWriteRequest(

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

}

接着,我们需要在messageSent()方法中做相反的转换。

publicvoidmessageSent(NextFilter nextFilter, IoSession session, Object message){

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

}

如何做StringByteBuffer的转换?因为我们不需要重构原始信息,因此可能更高效一些,即便如此,这个实现也比上一个例子复杂。

publicvoidfilterWrite(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()));

}

 

publicvoidmessageSent(NextFilter nextFilter, IoSession session, Object message){

    if(message instanceof MyByteBuffer){

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

    }else{

        nextFilter.messageSent(session, message);

    }

}

 

privatestaticclassMyByteBufferextends ByteBufferProxy {

    privatefinal Object originalValue;

    privateMyByteBuffer(Object originalValue, ByteBuffer encodedValue){

        super(encodedValue);

        this.originalValue= originalValue;

    }

}

假入你使用的是MINA2.0,将和1.01.1有所不同。请参考对应的CompressionFilter RequestResponseFilter.

4.4当过滤sessionCreated事件时要小心

sessionCreated是一个必须在I/O处理器线程中执行的事件(请参考配置线程模型)。千万不要把sessionCreated事件转发给其他线程。

publicvoidsessionCreated(NextFilter nextFilter, IoSession session)throws Exception {

    // ...

    nextFilter.sessionCreated(session);

}

 

// 千万别这么干

publicvoidsessionCreated(final NextFilter nextFilter,final IoSession session)throws Exception {

    Executor executor =...;

    executor.execute(new Runnable(){

        nextFilter.sessionCreated(session);

        });

    }

4.5当心空缓冲区

在某些情况下,MINA将一个空缓冲区作为一个内部信号使用。空缓冲区有时会变成一个问题,因为它是引起某些异常的原因,例如IndexOutOfBoundsException。接下来将说明如何避免这种意外情况发生。

ProtocolCodecFilter使用一个空缓冲区(buf.hasRemaining() = 0)来标示一个消息的结束。如果你的过滤器位于ProtocolCodecFilter之前,而且你的过滤器是可以在缓冲区为空时抛出一个异常,请确保你的过滤器把这个空缓冲区转发给下一个过滤器。

publicvoidmessageSent(NextFilter nextFilter, IoSession session, Object message){

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

        nextFilter.messageSent(nextFilter, session, message);

        return;

    }

    ...

}

 

publicvoidfilterWrite(NextFilter nextFilter, IoSession session, WriteRequest request){

    Object message = request.getMessage();

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

        nextFilter.filterWrite(nextFilter, session, request);

        return;

    }

    ...

}

我们是不是必须为每个过滤器都添加上面的if代码块?答案是不需要。下面是处理空缓冲区的黄金法则:

1)如果缓冲区为空时你的过滤器可以正常运行,你不需要添加上面的If代码块。

2)如果你的过滤器位于ProtocolCodecFilter之后,你不需要添加上面的if代码块。

3)除上述两种情况外,你都需要这个if代码块。

 

如果你需要这个if代码块,请记住你并不需要总是遵循上面的例子。如果你想要你的过滤器不管在什么情况下都不会抛出一个意想不到的异常的话,你可以检测一下缓冲区是否为空。

2
4
分享到:
评论

相关推荐

    mina学习笔记,记录所有API

    在MINA的学习笔记中,记录的所有API通常会包括以下几个核心部分: 1. **IoSession**: 这是MINA的核心接口,代表了客户端和服务器之间的连接。IoSession提供了读写数据、管理连接状态、获取会话属性等功能。例如,`...

    Mina学习笔记

    Apache Mina是一个基于Java的网络通信框架,专为高性能、高可用性和可扩展性而设计。...在深入学习Mina的过程中,理解IoService及其子类的工作原理,以及如何结合IoHandler实现业务逻辑,对于掌握Mina框架至关重要。

    MIna2.0学习笔记

    1. **下载使用的Jar包**:在开始Mina2.0的学习之前,你需要从Apache官网或其他可靠的源下载Mina的最新版本库。通常,这包括核心库和其他依赖库,如slf4j用于日志记录。 2. **工程创建配置**:创建一个新的Java项目...

    Apache Mina Server 2.0中文参考手册V1.0,Apache Mina2.0学习笔记(修订版)

    Apache Mina Server 2.0中文参考手册V1.0,Apache Mina2.0学习笔记(修订版)Apache Mina Server 2.0中文参考手册V1.0,Apache Mina2.0学习笔记(修订版)

    Mina2.0学习笔记(完整版).doc

    创建Mina项目时,需要引入必要的Mina库依赖,如mina-core,然后根据Mina提供的API来配置服务器和客户端,包括设置监听端口、选择传输协议、添加过滤器等。 **8. 服务端和客户端程序** 服务端程序通常包括初始化...

    Mina2.0学习笔记(修订版).

    Apache Mina是一个高性能、事件驱动的网络应用框架,主要用于简化开发服务器端的复杂性,尤其在处理TCP/IP、UDP和SSL/TLS等协议时。它提供了丰富的API和工具,使得开发者能够快速构建网络应用程序,如FTP、SMTP、...

    MINA 协议解码过滤器

    过滤器链的概念是MINA框架的核心特性之一,它允许开发者插入自定义的过滤器来处理进来的数据或者发送出去的数据。协议解码过滤器(ProtocolDecoderFilter)就是这样的一个过滤器,它的主要任务是从接收到的原始字节...

    apache mina 学习笔记三(子项目FtpServer)

    在本学习笔记中,我们将专注于MINA的子项目——FtpServer,它是实现FTP服务器功能的一个模块。 FTP(File Transfer Protocol)是一种广泛使用的互联网协议,用于在不同主机之间传输文件。Apache MINA FtpServer提供...

    Mina 学习笔记(入门)

    2. **组件结构**:Mina 包含几个核心组件,如Acceptor(监听器)、Session(会话)、Filter(过滤器)和ProtocolCodec(编码解码器)。这些组件协同工作,确保数据在网络间的高效传输。 ### 二、Mina 基础 #### 1....

    Apache mina2学习笔记DEMO

    在这个"Apache MINA2学习笔记DEMO"中,我们很可能会看到如何使用MINA来创建一个自定义协议的示例。自定义协议通常是为了满足特定应用的需求,例如高效的数据传输、安全性或者特定的编码格式。MINA允许开发者定义自己...

    Apache_Mina2.0学习笔记

    第五步.长连接VS短连接 8 二. Mina基础 9 1.IoService接口 10 2.1.1 类结构 11 2.1.2 应用 12 2.IoFilter接口 14 2.2.1 类结构 14 2.2.2 应用 16 添加过滤器 16 自定义编解码器 17 制定协议的方法: 19 IoBuffer...

    MINA学习笔记(仅供参考)

    ### MINA学习笔记 #### MINA概述 MINA是一个用Java编写的高性能、轻量级的网络通信框架,主要用于简化网络编程的复杂性。它支持多种传输协议(如TCP/IP和UDP/IP),并且提供了一套丰富的API来处理网络通信相关的...

Global site tag (gtag.js) - Google Analytics