我正在尝试实现一个缓存,该缓存将计算最近5分钟内登录尝试的次数,在我的代码中,我想检查用户是否尝试了超过MAX_ATTEMPTS次。
我在网上找到的所有针对“ Guava Cache”的代码示例都使用load方法从其他来源获取值或使用某些方法对其进行计算,那么每次遇到缓存命中时如何增加它的值?>
static LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.maximumSize(100000)
.expireAfterAccess(5, TimeUnit.MINUTES)
.build(
new CacheLoader<String, Integer>() {
public Integerload(String user) {
return ????;
}
}
);
稍后在运行时我要检查:
if(cache.getIfPresent(user) != null && cache.get(user) > MAX_ATTEMPTS)
,并在以下情况下增加它:
if(cache.getIfPresent(user) != null && cache.get(user) <= MAX_ATTEMPTS)
答案 0 :(得分:1)
您可以尝试修改以下代码段:
public class Demo {
public static void main(String[] x) {
CacheLoader<String, AtomicInteger> initialValueLoader = new CacheLoader<String, AtomicInteger>() {
@Override
public AtomicInteger load(String key) {
// do not care of the key. everybody starts with 0 login attempts.
return new AtomicInteger(0);
}
};
LoadingCache<String, AtomicInteger> c = CacheBuilder
.newBuilder()
.maximumSize(100000)
.expireAfterAccess(2, TimeUnit.SECONDS)
.build(initialValueLoader);
String user = "bob";
try {
// when the user tries to login, increment the attemps by one
Verify.verify(c.get(user).incrementAndGet() == 1);
// next call will get one
Verify.verify(c.get(user).get() == 1);
} catch (ExecutionException e) {
throw new RuntimeException("oups: " + e, e);
}
// simulate time
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
// after some time, the cache is cleared
try {
Verify.verify(c.get(user).get() == 0);
} catch (ExecutionException e) {
throw new RuntimeException("oups: " + e, e);
}
System.out.println("done.");
}
}
答案 1 :(得分:1)
@Oren您的解决方案不是线程安全的,因为您使用的是Cache外部的值。您最好使用Cache#asMap()
视图并在ConcurrentMap#compute(K, BiFunction<K, V, V>)
方法内更改值:
forgetPasswordCache.asMap().compute(email, (cachedEmail, currentCount) -> {
if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
logger.error("User with id: " + user.getId() + " and email: " + email +
" has reached the maximum number of reset password attempts, the mail will not be sent");
return null;
}
if (currentCount == null) {
return 1;
} else {
return currentCount + 1;
}
});
答案 2 :(得分:-1)
已解决,仅使用Guava的缓存功能(不使用加载程序)
缓存看起来像这样:
public class ForgetPasswordAttemptsCache {
private static final Cache<String, Integer> forgetPasswordCache = CacheBuilder.newBuilder()
.expireAfterAccess(24, TimeUnit.HOURS)
.build();
private ForgetPasswordAttemptsCache(){
}
public static Cache<String, Integer> getInstance() {
return forgetPasswordCache;
}
}
及其用途:
final String email = user.getEmail();
Integer currentCount = ForgetPasswordAttemptsCache.getInstance().getIfPresent(email);
if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
logger.error("User with id: " + user.getId() + " and email: " + email +
" has reached the maximum number of reset password attempts, the mail will not be sent");
return;
}
if (currentCount == null) {
ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(1));
} else {
ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(currentCount + 1));
}
感谢spi提供此解决方案。 (现在,我正在寻找一种无需运行24小时即可进行测试的方法。)