个人以为只要设定了timeToLiveSeconds,中间过程不管有没有访问,只要LiveSeconds时间到了,缓存就会失效。但是开发时发现并非如此,经过一番折腾,最终发现自己的理解是正确的,还是使用层面的问题。
需求:在用户登陆时,用户连续3次密码输入错误,账号则自动锁定5分钟, 存储时key为用户名,value为重试次数,当用户再次点击时,显示剩余的锁定时长。
对于每次登陆点击,系统需要记录日志,含尝试次数。
问题:第一次显示是没有问题,后面点击时发现剩余时间就不像预期了。
原因:在用ehcache存储时,由于没有更新值的方法,每次都是ehcache.put(new Element(key,value))来存储新的尝试次数,虽然key是一样,但是由于是新的对象,导致element的创建时间发生了变化,从而最终的存活时间点也向后发生了推移。
解决办法:
不能用new Element(key,value)),而应该采用另外一个构造方法:
public Element(final Object key, final Object value, final long version, final long creationTime, final long lastAccessTime, final long lastUpdateTime, final long hitCount) { this.key = key; this.value = value; this.version = version; this.lastUpdateTime = lastUpdateTime; HIT_COUNT_UPDATER.set(this, hitCount); this.creationTime = creationTime; this.lastAccessTime = lastAccessTime; }
在这个方法里面,创建时间,上次访问时间等属性可以直接设定。
个人完整代码如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.ehcache.EhCacheCache; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; public class ServiceBase { @Autowired protected CacheManager cacheManager; protected Element getCacheValue(String cacheName, String key) { Ehcache ehcache = this.getEhcache(cacheName); return ehcache.get(key); } protected void removeCache(String cacheName, String key) { Ehcache ehcache = this.getEhcache(cacheName); ehcache.remove(key); } protected void setCache(String cacheName, String key, Object value) { Ehcache ehcache = this.getEhcache(cacheName); Element element = ehcache.get(key); if (element == null) { element = new Element(key, value); } else { if (element.getTimeToLive() > 0 && element.getTimeToIdle() == 0) { element = new Element(key, value, 1L, element.getCreationTime(), element.getLastAccessTime(), element.getLastUpdateTime(), element.getHitCount()); } else { element = new Element(key, value); } } ehcache.put(element); } protected Ehcache getEhcache(String cacheName) { Cache cache = cacheManager.getCache(cacheName); EhCacheCache ehCacheCache = (EhCacheCache) cache; Ehcache nativeCache = ehCacheCache.getNativeCache(); return nativeCache; } }