個人以為只要設定了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; } }