diff --git a/starters/cache-spring-boot-starter/pom.xml b/starters/cache-spring-boot-starter/pom.xml index 75e466d0ea5d91b8c2a0a373b12825c7145924a7..cb35ee5ce3a67e360d1b0de1c43e18468595aab6 100644 --- a/starters/cache-spring-boot-starter/pom.xml +++ b/starters/cache-spring-boot-starter/pom.xml @@ -26,14 +26,6 @@ org.apache.commons commons-pool2 - - org.springframework.boot - spring-boot-starter-aop - - - org.redisson - redisson-spring-boot-starter - diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/CacheAutoConfiguration.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/CacheAutoConfiguration.java index bf6d068b0fae38e29de8b024d3feaf3db1bd01eb..c7df7c492489d6dbb7218dd964520c79b42a96d8 100644 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/CacheAutoConfiguration.java +++ b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/CacheAutoConfiguration.java @@ -1,18 +1,11 @@ package com.schbrain.framework.autoconfigure.cache; -import com.schbrain.common.util.JacksonUtils; -import com.schbrain.framework.autoconfigure.cache.concurrent.RateLimitAspect; import com.schbrain.framework.autoconfigure.cache.properties.CacheProperties; import com.schbrain.framework.autoconfigure.cache.provider.CacheProvider; import com.schbrain.framework.autoconfigure.cache.provider.CacheProviderDelegate; import com.schbrain.framework.autoconfigure.cache.provider.redis.RedisCacheConfiguration; -import org.redisson.api.RedissonClient; -import org.redisson.codec.JsonJacksonCodec; -import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -37,17 +30,4 @@ public class CacheAutoConfiguration { return provider; } - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(RedissonClient.class) - public RateLimitAspect rateLimitAspect(ConfigurableListableBeanFactory beanFactory, RedissonClient redissonClient) { - return new RateLimitAspect(beanFactory, redissonClient); - } - - @Bean - @ConditionalOnBean(RedissonClient.class) - public RedissonAutoConfigurationCustomizer redissonConfigurationCodecCustomizer() { - return config -> config.setCodec(new JsonJacksonCodec(JacksonUtils.getObjectMapper())); - } - } diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/ExpressionParser.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/ExpressionParser.java deleted file mode 100644 index d191ee13b50c9b23bef8e0d1f1095a4c67e11b9c..0000000000000000000000000000000000000000 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/ExpressionParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.schbrain.framework.autoconfigure.cache.concurrent; - -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.expression.Expression; -import org.springframework.expression.ParserContext; -import org.springframework.expression.common.TemplateParserContext; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author liaozan - * @since 2023-07-15 - */ -public class ExpressionParser { - - private final Map expressionCache = new ConcurrentHashMap<>(256); - - private final SpelExpressionParser parser = new SpelExpressionParser(); - private final ParserContext parserContext = new TemplateParserContext(); - - private final ConfigurableListableBeanFactory beanFactory; - - public ExpressionParser(ConfigurableListableBeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - public String parse(String value, Map variables) { - String resolved = beanFactory.resolveEmbeddedValue(value); - Expression expression = expressionCache.computeIfAbsent(resolved, this::parseExpression); - StandardEvaluationContext context = new StandardEvaluationContext(); - context.setBeanResolver(new BeanFactoryResolver(beanFactory)); - context.setVariables(variables); - return expression.getValue(context, String.class); - } - - private Expression parseExpression(String value) { - return parser.parseExpression(value, parserContext); - } - -} diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/NoOpRateLimitCacheKeyVariablesContributor.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/NoOpRateLimitCacheKeyVariablesContributor.java deleted file mode 100644 index a728680a71038bc953af4c229d7b4e065777cf65..0000000000000000000000000000000000000000 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/NoOpRateLimitCacheKeyVariablesContributor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.schbrain.framework.autoconfigure.cache.concurrent; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.reflect.MethodSignature; - -import java.util.Collections; -import java.util.Map; - -/** - * @author liaozan - * @since 2022/5/5 - */ -public class NoOpRateLimitCacheKeyVariablesContributor implements RateLimitCacheKeyVariablesContributor { - - @Override - public Map contribute(RateLimiter rateLimiter, JoinPoint joinPoint, MethodSignature signature) { - return Collections.emptyMap(); - } - -} diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitAspect.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitAspect.java deleted file mode 100644 index 3e6b6a2203df14d78133f55582b3efc505a19f45..0000000000000000000000000000000000000000 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitAspect.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.schbrain.framework.autoconfigure.cache.concurrent; - -import com.schbrain.common.exception.BaseException; -import com.schbrain.common.util.ApplicationName; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.reflect.MethodSignature; -import org.redisson.api.RRateLimiter; -import org.redisson.api.RateIntervalUnit; -import org.redisson.api.RateType; -import org.redisson.api.RedissonClient; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static com.schbrain.common.util.ParameterDiscoverUtils.getMethodArgsMap; - -/** - * @author liaozan - * @see RateLimiter - * @since 2022/5/5 - */ -@Slf4j -@Aspect -public class RateLimitAspect { - - private final Map rateLimiterMap = new ConcurrentHashMap<>(); - private final Map, RateLimitCacheKeyVariablesContributor> contributorMap = new ConcurrentHashMap<>(); - - private final String keyPrefix; - private final RedissonClient redissonClient; - private final ExpressionParser expressionParser; - - public RateLimitAspect(ConfigurableListableBeanFactory beanFactory, RedissonClient redissonClient) { - this.keyPrefix = ApplicationName.get(); - this.redissonClient = redissonClient; - this.expressionParser = new ExpressionParser(beanFactory); - } - - @Before("@annotation(annotation)") - public void beforeExecute(JoinPoint joinPoint, RateLimiter annotation) { - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - doRateLimit(annotation, joinPoint, methodSignature); - } - - protected void doRateLimit(RateLimiter annotation, JoinPoint joinPoint, MethodSignature signature) { - Map variables = prepareVariables(annotation, joinPoint, signature); - - String cacheKey = expressionParser.parse(annotation.cacheKey(), variables); - if (cacheKey == null) { - throw new BaseException("cacheKey should not be null"); - } - - String formattedCacheKey = formatCacheKey(cacheKey); - RRateLimiter rateLimiter = rateLimiterMap.computeIfAbsent(formattedCacheKey, key -> createRateLimiter(key, annotation)); - - if (rateLimiter.tryAcquire()) { - return; - } - throw new BaseException("The access frequency is too fast, please try again later"); - } - - protected String formatCacheKey(String cacheKey) { - return "rateLimit:" + keyPrefix + ":" + cacheKey; - } - - protected RRateLimiter createRateLimiter(String cacheKey, RateLimiter annotation) { - RRateLimiter rateLimiter = redissonClient.getRateLimiter(cacheKey); - rateLimiter.setRate(RateType.PER_CLIENT, annotation.permits(), annotation.expireTime(), RateIntervalUnit.valueOf(annotation.unit().name())); - return rateLimiter; - } - - private Map prepareVariables(RateLimiter annotation, JoinPoint joinPoint, MethodSignature signature) { - Map variables = getMethodArgsMap(signature.getMethod(), joinPoint.getArgs()); - Class contributorClass = annotation.contributor(); - if (contributorClass == null || contributorClass == NoOpRateLimitCacheKeyVariablesContributor.class) { - return variables; - } - - RateLimitCacheKeyVariablesContributor contributor = contributorMap.get(contributorClass); - if (contributor == null) { - contributor = BeanUtils.instantiateClass(contributorClass); - contributorMap.put(contributorClass, contributor); - } - Map contributeVariables = contributor.contribute(annotation, joinPoint, signature); - if (MapUtils.isNotEmpty(contributeVariables)) { - variables.putAll(contributeVariables); - } - return variables; - } - -} diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitCacheKeyVariablesContributor.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitCacheKeyVariablesContributor.java deleted file mode 100644 index 41d0b7db76132adb57aa92f4674683191c6483f9..0000000000000000000000000000000000000000 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimitCacheKeyVariablesContributor.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.schbrain.framework.autoconfigure.cache.concurrent; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.reflect.MethodSignature; - -import java.util.Map; - -/** - * @author liaozan - * @since 2022/5/5 - */ -public interface RateLimitCacheKeyVariablesContributor { - - Map contribute(RateLimiter rateLimiter, JoinPoint joinPoint, MethodSignature signature); - -} diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimiter.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimiter.java deleted file mode 100644 index ac04a76b5395841f0cc5f72bf46bc7a962a5b8cf..0000000000000000000000000000000000000000 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/concurrent/RateLimiter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.schbrain.framework.autoconfigure.cache.concurrent; - -import java.lang.annotation.*; -import java.util.concurrent.TimeUnit; - -/** - * @author liaozan - * @since 2022/5/5 - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RateLimiter { - - /** - * 过期时间 - */ - long expireTime() default 10; - - /** - * 过期时间单位 - */ - TimeUnit unit() default TimeUnit.SECONDS; - - /** - * 过期时间内允许的许可数 - */ - int permits() default 3; - - /** - * 缓存的 key,使用 spring el 进行解析 - */ - String cacheKey(); - - /** - * evaluation variables contributor - */ - Class contributor() default NoOpRateLimitCacheKeyVariablesContributor.class; - -} diff --git a/support/schbrain-spring-support/pom.xml b/support/schbrain-spring-support/pom.xml index 2a5e1466094190950b93f87686096facc973df83..c093c2a7c2f0547a12b3624438968c1f4536d9a7 100644 --- a/support/schbrain-spring-support/pom.xml +++ b/support/schbrain-spring-support/pom.xml @@ -22,6 +22,10 @@ org.springframework.boot spring-boot-starter-actuator + + org.springframework.boot + spring-boot-starter-aop + org.springframework.boot spring-boot-configuration-processor