JSF-对应用程序作用域Bean的扩展读写



在我的XPages web应用程序(XPages是一种基于JSF的Lotus Notes技术)中,我需要一个动态映射来存储会话ID和上次访问时间(以毫秒为单位)。这是作为应用程序范围的bean中的TreeMap实现的。对应用程序的每次初始访问都会将当前会话注册到此bean中的TreeMap。此映射只允许有限数量的会话条目,并且不会注册多余的会话。映射也会偶尔从旧会话条目中清除一次,以便可以注册新会话 我需要知道这是否是一种可接受的方法/应用程序bean的使用 我知道我可以将会话条目临时存储在外部DB(非lotus notes)中,但我所在的公司不允许我这样做。这种方法会给我带来潜在的问题吗?如果是,我还有别的办法吗?

这听起来像是对应用程序bean的完全有效的使用,但我有两个建议。第一种是使用ConcurrentSkipListMap而不是TreeMap。前者是线程安全的,而后者则不是。当与较低的作用域交互时,线程安全通常并不重要,因为每个用户只能写入自己的会话、视图和请求作用域,但所有用户都可以写入应用程序作用域,因此可以想象可能会发生并发写入,尤其是在用户负载较重的应用程序中。第二个建议是提醒注意在应用程序bean中存储了多少关于每个会话的信息。由于所有用户都可以访问bean,因此理论上可能会无意中向其他用户暴露太多关于某个用户的信息。如果除了上次访问时间之外,您只存储会话名称或ID,那么您就可以了。但是,如果你实际上存储了一个指向每个用户会话范围的指针,你可能会意外地提供一个窗口,显示用户缓存的其他用户不应该访问的数据。我从未见过有人被这种情况困扰,但在应用程序范围中存储任何特定于用户的信息时,记住这一点总是很重要的。

事实上,这是应用程序范围的一个很好的使用。尽管如此,TreeMap集合并不是适合您情况的最佳方法,这也存在一些问题:

  • 当2个请求想要修改容器中的数据时出现并发问题
  • 如果应用程序必须水平扩展,那么在每个托管bean中将有2个TreeMap

一个好的方法是使用缓存系统。有一些好的缓存库可以满足这些要求,我已经测试了ehcache,它为处理数据和库提供了并发管理,以防您有2个或多个节点来部署应用程序,您还可以配置基于LRU(使用频率较低)或FIFO(先进先出)的算法来清除缓存。

使用外部数据库来处理会话ID可能会花费一些时间来获取/设置数据(数据可能非常低,但仍然是磁盘I/O操作)。对于这个问题,您可以使用BigMemory作为RAM中的外部数据库,或者使用像BigTable这样的NoSQL数据库。

注意:我不为ehcache工作,也没有商业关联,我已经测试过了,它满足了我的需求。,还有其他缓存系统库,如JBoss cache和其他可以评估和使用的库。

最新更新