springboot高级教程基于 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配置负载均衡的服务宕机了,怎么配置高可用

加群交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java知路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值