说明:实际开发中,我们在前端页面上点击了一个按钮,访问了一个接口,这时因为网络波动或者其他原因,页面上没有反应,用户可能会在短时间内再次点击一次或者用户以为没有点到,很快的又点了一次。导致短时间内发送了两个请求到后台,可能会导致数据重复添加。
为了避免短时间内对一个接口访问,我们可以通过AOP+自定义注解+Redis的方式,在接口上加一个自定义注解,然后通过AOP的前置通知,在Redis中存入一个有效期的值,当访问接口时这个值还未过期,则抛出异常,以此来避免短时间内对接口的方法。
实现
第一步:创建一个自定义注解,设置两个属性,一个是key,一个是这个key在Redis中的有效时间;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自定义注解 */ @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public @interface LimitAccess { /** * 限制访问的key * @return */ String key(); /** * 限制访问时间 * @return */ int times(); } |
第二步:创建对应的Aspect;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import com.hezy.annotation.LimitAccess; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; /** * AOP类(通知类) */ @Component @Aspect public class LimitAspect { @Autowired private RedisTemplate redisTemplate; @Pointcut ( "@annotation(com.hezy.annotation.LimitAccess)" ) public void pt(){}; @Around ( "pt()" ) public Object aopAround(ProceedingJoinPoint pjp) throws Throwable { // 获取切入点上面的自定义注解 Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; // 获取方法上面的注解 LimitAccess limitAccess = methodSignature.getMethod().getAnnotation(LimitAccess. class ); // 获取注解上面的属性 int limit = limitAccess.times(); String key = limitAccess.key(); // 根据key去找Redis中的值 Object o = redisTemplate.opsForValue().get(key); // 如果不存在,说明是首次访问,存入Redis,过期时间为limitAccess中的time if (o == null ) { redisTemplate.opsForValue().set(key, "" , limit, TimeUnit.SECONDS); // 执行切入点的方法 return pjp.proceed(); } else { // 如果存在,说明不是首次访问,抛出异常 throw new RuntimeException( "访问过于频繁" ); } } } |
第三步:在需要限制的接口上,加上这个注解,并设置key和限制访问时间,如下这个这个接口,设置key为limit,实际开发中可以设置一个随机值,或者按照规则自定义设置,times为限制访问时间;
1 2 3 4 5 | @GetMapping("/limit") @LimitAccess(key = "limit", times = 10) public String limit() { return "success"; } |
演示
启动项目,访问该接口;
(首次访问,没得问题,同时在Redis中存入值)
(短时间内,连续访问,因为Redis中值未过期)
(10秒之后再访问,又可以了,Redis中的值过期了)
以上就是使用Redis实现接口防抖,避免短时间内连续访问接口。实际开发中,可以将异常设置为自定义异常。
到此这篇关于Redis实现接口防抖的示例代码的文章就介绍到这了,更多相关Redis 接口防抖内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!