我正在尝试实现一个缓存,它将统计过去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)发布于 2018-10-10 21:46:09
@Oren你的解决方案不是线程安全的,因为你是在Cache之外的值上操作。最好使用Cache#asMap()视图,并在ConcurrentMap#compute(K, BiFunction)方法中更改值:
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;
}
});发布于 2018-10-09 16:08:38
您可以尝试改编以下代码片段:
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.");
}
}发布于 2018-10-09 17:07:33
通过仅使用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小时运行的测试。)
https://stackoverflow.com/questions/52703795
复制相似问题