xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RedisRateLimiterClient.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package org.springblade.core.redis.ratelimiter;
import lombok.RequiredArgsConstructor;
import org.springblade.core.tool.utils.CharPool;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * redis é™æµæœåŠ¡
 *
 * @author dream.lu
 */
@RequiredArgsConstructor
public class RedisRateLimiterClient implements RateLimiterClient {
   /**
    * redis é™æµ key å‰ç¼€
    */
   private static final String REDIS_KEY_PREFIX = "limiter:";
   /**
    * å¤±è´¥çš„默认返回值
    */
   private static final long FAIL_CODE = 0;
   /**
    * redisTemplate
    */
   private final StringRedisTemplate redisTemplate;
   /**
    * redisScript
    */
   private final RedisScript<List<Long>> script;
   /**
    * env
    */
   private final Environment environment;
   @Override
   public boolean isAllowed(String key, long max, long ttl, TimeUnit timeUnit) {
      // redis key
      String redisKeyBuilder = REDIS_KEY_PREFIX +
         getApplicationName(environment) + CharPool.COLON + key;
      List<String> keys = Collections.singletonList(redisKeyBuilder);
      // æ¯«ç§’,考虑主从策略和脚本回放机制,这个time由客户端获取传入
      long now = System.currentTimeMillis();
      // è½¬ä¸ºæ¯«ç§’,pexpire
      long ttlMillis = timeUnit.toMillis(ttl);
      // æ‰§è¡Œå‘½ä»¤
      List<Long> results = this.redisTemplate.execute(this.script, keys, max + "", ttlMillis + "", now + "");
      // ç»“果为空返回失败
      if (results == null || results.isEmpty()) {
         return false;
      }
      // åˆ¤æ–­è¿”回成功
      Long result = results.get(0);
      return result != FAIL_CODE;
   }
   private static String getApplicationName(Environment environment) {
      return environment.getProperty("spring.application.name", "");
   }
}