前言
我计划使用 ehCache 作为会话管理实现首先检查,如果你不能使用已经提供的,并且可能更适合会话实现。如果您使用的是 Web 容器或完整的 jee 服务器,您真的应该先尝试一下
为什么
好的。你肯定不会用正确的简单方法来做这件事。这里有一些提示,为什么您可能希望使用 ehCache 进行会话
- 您的服务不是 jee 服务器/Web 容器的一部分。
- 您的服务是无状态的,但有时您需要状态(框架代码)。
- 由于您和可区分客户端之间的代理,您无法区分调用,例如,您是某种服务/服务的中间件,默认情况下不提供可区分数据,但有条件地使用 userId 或 sessionId 等参数,但不是组成性的。
- 您只是没有 RTFM,而是想按照自己的方式来做。
对于 1,请检查是否可以选择像码头这样的网络容器。你当然会使用整个会话的网络访问,这不会为你弹出。
对于 2,请检查,如果Apache Shiro不会做你想做的事。如果没有,ehCache 可能是你的朋友。
3 ... 欢迎来到俱乐部。
对于 4... 好吧,我想如果您没有阅读手册,您也不会阅读此内容。
如何
如果您想使用 ehCache 实现会话管理,请确保您的数据是可序列化的。这将减少问题并让您使用 ehCache 的敏感功能。即持久化到磁盘、缓存节点、从中恢复等等。
不要为每个会话使用一个缓存,而是为所有会话使用一个缓存。是缓存上的键,值将转到. 不要忘记并发(想想 ajax 调用)。最好使用from 。但也许你是Heinz M. Kabutz 博士,并找到一种更酷的方法来做到这一点。sessionId
Map
ConcurrentHashMap
java.util.concurrent
我发现使用大小而不是存储元素的数量非常有帮助。您可能不知道以后会存储哪些数据/对象。不要忘记设置持久性策略。我在这里使用存储到临时文件夹。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir"/>
<cache name="vocCache"
eternal="false"
maxElementsInMemory="100MB"
maxElementsOnDisk="1GB"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
memoryStoreEvictionPolicy="LRU"
diskExpiryThreadIntervalSeconds="60">
<persistence strategy="localTempSwap" />
</cache>
因为我们想实现一个会话管理器,所以我们不关心timeToLiveSeconds
. 会话在一定的空闲时间后超时。因此,我们不将元素限制为最大 ttl,而是使用timeToIdleSeconds
让元素超时。不要打扰timeToIdleSeconds
andtimeToLiveSeconds
因为您可以为元素设置特定值以便以后添加。
驱逐
关于到期时间的注释。内存中的元素永远不会因为配置的时间而被驱逐。内存将累积,直到达到定义的内存约束。因此,如果您定义 100 个元素,如果添加了 101 个元素,memoryStoreEvictionPolicy
将触发下注并且一个元素将 - 在此配置中 - 刷新到磁盘 (ehCache 2.2)。对于磁盘存储,将有一个线程检查到期时间(diskExpiryThreadIntervalSeconds
)。请参阅文档。因此,您必须检查从缓存中检索到的元素,isExpired()
以确保它没有过期。
所以最后,你会得到这样的结果:
得到
Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
Element elem = cache.get(identifier);
if (elem == null)
{
throw new SessionNotFoundException(identifier);
}
if (elem.isExpired())
{
throw new SessionExpiredException(identifier);
}
return elem.getObjectValue();
放
Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
// We use ttl = 0 and tti=<ttlInMinutes>, because session timeout is based on session idle timout.
element = new Element(identifier, new SessionElement(), Boolean.FALSE, (int) (timeToLive / VALUE_MS), 0);
cache.put(element);