在MINA中,session处于核心地位:每当一个客户端连接到服务器上时,一个新的session就会被创建,它会被保存到内存中,直到客户端断开连接。Session被用来保存持久的连接信息,还会附加一些服务器在处理请求时可能需要的任何其他种类的信息,这些信息在session的整个生命周期中都是生效的。
(补充:由于该手册官方也在不断完善中,因此会有变化,最近一次更新时间为2012-12-22,强烈建议看
原文
)
Session的状态会随着时间演变:
- 已连接:session已被创建并是可用的状态
- 空闲:session在一段指定的时间(该时间可配置)内没有处理过任何请求
- 读空闲:在一段时间内没有读请求被处理
- 写空闲: 在一段时间内没有写请求被处理
- 读写空闲: 在一段时间内既没有读请求、也没有写请求被处理
- 关闭中:session正在被关闭(剩余的被缓存的消息正在被写入到底层流以刷新,清理工作尚未完全终止)
- 已关闭:session已经被关闭,并无法被重新激活
下面的状态图显示了session所有可能的状态和其之间的状态转换关系:
对于一个Session有很多不同的参数可以被设置:
- 消息接收缓冲区大小
- 消息发送缓冲区大小
- 空闲时间
- 写入超时
还有一些其他取决于所使用的具体的传输类型的配置(参见第六章 传输)
系统开发过程中,我们通常需要保存一些数据以备后面使用,这通常要使用一种专用的数据结构来完成,这种数据结构只和当前的Session相关联。这就是键值组合“key-value”的数据结构,它可以用来存储开发人员所需的任何数据类型。
例如,如果你想追踪从一个session被创建开始,一个用户一共发起了多少次请求的数据,可以通过简单地将该数据保存到该map中即可——通过创建一个键key来关联这个值value:
... int counterValue = session.getAttribute( "counter" ); session.setAttribute( "counter", counterValue + 1 ); ...
我们有一种方法来处理存储到Session中的属性Attribute:一个Attribute属性就是一个键值对,在Session的容器中可以对它进行添加,删除和读取等操作。
这个容器伴随着Session的创建而自动创建,伴随着Session的终止而被清除。
自定义数据容器
这个上面曾提到过,这个容器是一个key/value容器,默认是一个map,但也可以自定义一个其他类型的数据结构,比如,有时希望处理长时间存在的数据,或想避免在内存中保存较大的数据:我们可以通过实现一个接口和一个工厂,以使session在创建时通过调用我们自定的实现来完成容器的创建。
下面的代码片段显示了一个session在初始化时如何创建这个容器的:
protected final void initSession(IoSession session, IoFuture future, IoSessionInitializer sessionInitializer) { ... try { ((AbstractIoSession) session).setAttributeMap(session.getService() .getSessionDataStructureFactory().getAttributeMap(session)); } catch (IoSessionInitializationException e) { throw e; } catch (Exception e) { throw new IoSessionInitializationException( "Failed to initialize an attributeMap.", e); } ...
而这里显示的就是当我们想要自定义一个其他类型的容器时,我们需要实现的那个工厂接口的代码:
public interface IoSessionDataStructureFactory { /** * Returns an {@link IoSessionAttributeMap} which is going to be associated * with the specified <tt>session</tt>. Please note that the returned * implementation must be thread-safe. */ IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception; }
过滤器链
每个Session都关联着一串过滤器,当接收传入的请求或向外传出消息时这些过滤器就会处理这些信息。这些过滤器是单独针对每个Session的,大多数情况下,我们对当前所有的session都是使用几乎完全一样的过滤器链。然而,动态地修改某个单独的session也是允许的,例如,可以对一个特定的session添加一个日志过滤器。
统计
每个session都会保持跟踪有关该session执行情况的记录,如:
- 接收或发送的字节数量
- 接收或发送的消息数量
- 空闲状态
- 吞吐量
以及,很多其他有用的信息。
处理程序Handler
最后,一个session必须附带一个处理程序Handler,它不仅负责调度消息到你的应用中,也通过简单地调用session的write()方法,将响应传回:
... session.write( <your message> ); ...