问题
如下代码是获取短信验证码功能,会先检查下前面五分钟内发没发过验证码,也就是有没有手机号对应缓存key,有的话刷新过期时间,没有就缓存一下设置过期时间为5分钟。
但是经过测试在第一次发送时缓存的key没有设置过期时间,也就是说永不过期,当再发送一次后过期时间就正常刷新为5分钟了。
@override
public void getsmscaptcha(string phone) {
string hashkey = "login:sms:captcha:" + phone;
boundhashoperations<string, string, string> hashops = stringredistemplate.boundhashops(hashkey);
// 初始检查
string lastsendtimestamp = hashops.get("lastsendtimestamp");
string sendcount = hashops.get("sendcount");
string captcha = hashops.get("captcha");
hashops.expire(5, timeunit.minutes); // 设置过期时间为5分钟
// 判断发送次数是否超过限制
if (stringutils.isnotblank(sendcount) && integer.parseint(sendcount) >= 5) {
hashops.expire(24, timeunit.hours); // 重新设置过期时间为24h
throw new generalbusinessexception("发送次数过多,请24h后再试");
}
// 判断发送频率是否过高
if (stringutils.isnotblank(lastsendtimestamp)) {
long lastsendtime = long.parselong(lastsendtimestamp);
long currenttime = system.currenttimemillis();
long elapsedtime = currenttime - lastsendtime;
long interval = 60 * 1000; // 60秒
if (elapsedtime < interval) {
throw new generalbusinessexception("发送短信过于频繁,请稍后再试");
}
}
// 更新发送次数
int newsendcount = stringutils.isnotblank(sendcount) ? integer.parseint(sendcount) + 1 : 1;
// 生成新验证码
if (stringutils.isblank(captcha)) {
captcha = randomstringutils.randomnumeric(6);
}
// 发送短信
if (!smsutil.sendsms(phone, captcha)) {
throw new generalbusinessexception("发送短信失败");
}
// 更新 redis 中的信息
hashops.put("captcha", captcha);
hashops.put("lastsendtimestamp", string.valueof(system.currenttimemillis()));
hashops.put("sendcount", string.valueof(newsendcount));
}
原因
boundhashoperations<string, string, string> hashops = stringredistemplate.boundhashops(hashkey);
使用 boundhashops 方法时指定的 hashkey 在 redis 中不存在,那么 boundhashops 将返回一个空的 boundhashoperations 对象。这个对象仍然是可用的,但不包含任何数据。当第一次发送时,上面代码会先获取这个key,并设置过期时间为5分钟,但其实这个key不存在导致设置过期时间失败但是没有任何报错,当第二次发送时,检查到这个key存在了,过期时间就设置成功了。
解决方案
把刷新缓存时间操作放在put数据之后,这样保证了这个key存在后再设置过期时间。
@override
public void getsmscaptcha(string phone) {
string hashkey = "login:sms:captcha:" + phone;
boundhashoperations<string, string, string> hashops = stringredistemplate.boundhashops(hashkey);
// 初始检查
string lastsendtimestamp = hashops.get("lastsendtimestamp");
string sendcount = hashops.get("sendcount");
string captcha = hashops.get("captcha");
//。。。。。。。。。。。。。。。。。。。。。。。
// 更新 redis 中的信息
hashops.put("captcha", captcha);
hashops.put("lastsendtimestamp", string.valueof(system.currenttimemillis()));
hashops.put("sendcount", string.valueof(newsendcount));
//设置数据后再设置过期时间
hashops.expire(5, timeunit.minutes); // 设置过期时间为5分钟
}到此这篇关于spring boot中redis操作hash踩坑解决的文章就介绍到这了,更多相关springboot redis操作hash内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论