当前位置:   article > 正文

springboot高级教程基于 redis 通过注解实现限流_redis限流注解

redis限流注解

Spring Boot整合Redis有一种方便的方式是使用注解方式实现限流。

可以通过自定义注解的方式来标注需要限流的方法,在方法执行前进行限流的检查。

以下是具体实现方式:

1. 自定义注解`@RedisLimit`,并定义注解元素,如限流的时间、限流的次数等。
2. 编写切面类`RedisLimitAspect`,在方法执行前调用`RedisLimit`组件实现限流。
3. 将`RedisLimitAspect`类加入Spring容器中,以便进行注入。
4. 在需要进行限流的方法上添加`@RedisLimit`注解。

以下是示例代码:

`@RedisLimit`注解:

 

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RedisLimit {
    int limit() default 10;
    int timeout() default 60;
    String key() default "";}



切面类`RedisLimitAspect`:
 

@Aspect@Componentpublic class RedisLimitAspect {
    @Autowired    private RedisTemplate<String, String> redisTemplate;
    @Pointcut("@annotation(redisLimit)")    public void pointcut(RedisLimit redisLimit) {}
    @Before("pointcut(redisLimit)")    public void before(JoinPoint joinPoint, RedisLimit redisLimit) throws Throwable {        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())                .getRequest();        String ip = IpUtils.getRequestIp(request);        String key = redisLimit.key().equals("") ? ip : redisLimit.key();        int limit = redisLimit.limit();        int timeout = redisLimit.timeout();        if (!redisLimit(redisTemplate, key, limit, timeout)) {            throw new RuntimeException("限流了");        }    }
    /**     * 判断Redis中的key对应的值,是否满足小于limit     *     * @param redisTemplate RedisTemplate     * @param key           键     * @param limit         限流次数     * @param timeout       超时时间(秒)     * @return 是否限流     */    private boolean redisLimit(RedisTemplate<String, String> redisTemplate, String key, int limit, int timeout) {        String value = String.valueOf(System.currentTimeMillis() / 1000);        try {            redisTemplate.watch(key);            List<String> list = redisTemplate.opsForList().range(key, 0, -1);            int count = 0;            if (list != null && !list.isEmpty()) {                for (String time : list) {                    if (Long.parseLong(time) >= (System.currentTimeMillis() / 1000 - timeout)) {                        count++;                    } else {                        redisTemplate.opsForList().trim(key, count, -1);                        break;                    }                }            }            if ((count + 1) > limit) {                return false;            }            redisTemplate.multi();            redisTemplate.opsForList().rightPush(key, value);            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);            redisTemplate.exec();        } catch (Exception e) {            e.printStackTrace();            return false;        } finally {            redisTemplate.unwatch();        }        return true;    }
}



在需要进行限流的方法上添加`@RedisLimit`注解:
 

@RestControllerpublic class TestController {
    @GetMapping("/test")    @RedisLimit(key = "testKey", limit = 5, timeout = 60)    public String test() {        return "success";    }
}



注意:在使用`@RedisLimit`注解时,每个方法对应的key不应该相同,否则会出现相互干扰的情况。

推荐阅读

springboot 高级教程 如何优雅使用redission分布式锁

springboot 高级教程 全局异常处理

springboot mysql读写分离

什么是缓存穿透,如何避免

MySQL 百万级数据分页查询及优化

nginx配置负载均衡的服务宕机了,怎么配置高可用

加群交流

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/454981
推荐阅读
相关标签
  

闽ICP备14008679号