说到防止重复提交,解决方案有很多。比如使用token、redis、表字段唯一约束、时间戳判断等。本篇文章介绍一下redis防止重复提交。
第一次遇到这个问题,是在我们的app点赞功能发现的。产品要求点赞只能点一次,但是发现快速多次点赞也是可以成功的。因为客户端在第一次请求接口后,还没有来得及把点赞图标置灰,就发起了第二次请求。
最后这个问题的解决方案是利用redis原子特性解决,在接口请求后设置一个短有效期的缓存,下次接口请求时继续设置这个缓存,如果缓存没有设置成功则代表重复提交。
下面说一下具体实现:
1.redis依赖
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-redis</artifactid> </dependency>
2.redis配置
package com.example.redis.config; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.data.redis.connection.redisconnectionfactory; import org.springframework.data.redis.core.redistemplate; import org.springframework.data.redis.serializer.genericjackson2jsonredisserializer; import org.springframework.data.redis.serializer.stringredisserializer; /** * redis配置类 * @author murphy * @date 2024/6/6 */ @configuration public class redisconfig { @bean public redistemplate<string, object> redistemplate(redisconnectionfactory connectionfactory) { redistemplate<string, object> template = new redistemplate<>(); template.setconnectionfactory(connectionfactory); template.setkeyserializer(new stringredisserializer()); template.setvalueserializer(new genericjackson2jsonredisserializer()); return template; } }
3.application.yml配置redis连接信息
spring: redis: host: 127.0.0.1 port: 6379 database: 0
4.redis缓存操作实现
在这里我们使用redistemplate的setifabsent方法设置了缓存并设置了一个10s的有效期,具体过期时间可以根据业务来定。setifabsent方法的意思是如果缓存之前不存在,设置成功后返回true。如果缓存之前存在了则不进行设置并且返回false。
package com.example.redis.service; import org.springframework.beans.factory.annotation.autowired; import org.springframework.data.redis.core.redistemplate; import org.springframework.stereotype.service; import java.util.concurrent.timeunit; /** * redis操作实现 * @author murphy * @date 2024/6/6 */ @service public class redisservice { private static final int ttl = 10; // 过期时间,单位是秒 @autowired private redistemplate<string, object> redistemplate; public boolean preventduplicatesubmission(string userid) { string key = "praise_:" + userid; boolean success = redistemplate.opsforvalue().setifabsent(key, "1", ttl, timeunit.seconds); return boolean.true.equals(success); } }
5.测试
我们可以根据preventduplicatesubmission方法的返回结果来判断是否属于重复提交。下面模拟多次请求:
@test void contextloads() { boolean res1 = redisservice.preventduplicatesubmission("1"); system.out.println("第一次提交结果:" + res1); boolean res2 = redisservice.preventduplicatesubmission("1"); system.out.println("第二次提交结果:" + res2); boolean res3 = redisservice.preventduplicatesubmission("1"); system.out.println("第三次提交结果:" + res3); }
返回结果:
到此这篇关于redis防止重复提交的实现示例的文章就介绍到这了,更多相关redis防止重复提交内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论