diff --git a/api-boot-project/api-boot-autoconfigure/pom.xml b/api-boot-project/api-boot-autoconfigure/pom.xml index 7c7983fd..1224873e 100644 --- a/api-boot-project/api-boot-autoconfigure/pom.xml +++ b/api-boot-project/api-boot-autoconfigure/pom.xml @@ -126,6 +126,16 @@ minbox-mongo-client-settings true + + org.minbox.framework + minbox-ratelimiter + true + + + org.minbox.framework + minbox-resource-load + true + diff --git a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterAutoConfiguration.java b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterAutoConfiguration.java index 4611fc6d..eba8030f 100644 --- a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterAutoConfiguration.java +++ b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterAutoConfiguration.java @@ -17,13 +17,13 @@ package org.minbox.framework.api.boot.autoconfigure.ratelimiter; -import org.minbox.framework.api.boot.limiter.ApiBootRateLimiter; -import org.minbox.framework.api.boot.limiter.aop.advisor.ApiBootRateLimiterAdvisor; -import org.minbox.framework.api.boot.limiter.aop.interceptor.ApiBootRateLimiterMethodInterceptor; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.minbox.framework.api.boot.limiter.centre.support.DefaultRateLimiterConfigCentre; -import org.minbox.framework.api.boot.limiter.result.RateLimiterOverFlowResponse; -import org.minbox.framework.api.boot.limiter.support.GoogleGuavaRateLimiter; +import org.minbox.framework.limiter.MinBoxRateLimiter; +import org.minbox.framework.limiter.aop.advisor.RateLimiterAdvisor; +import org.minbox.framework.limiter.aop.interceptor.RateLimiterMethodInterceptor; +import org.minbox.framework.limiter.centre.RateLimiterConfigCentre; +import org.minbox.framework.limiter.centre.support.DefaultRateLimiterConfigCentre; +import org.minbox.framework.limiter.result.RateLimiterOverFlowResponse; +import org.minbox.framework.limiter.support.GoogleGuavaRateLimiter; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -41,7 +41,7 @@ * @author 恒宇少年 */ @Configuration -@ConditionalOnClass(ApiBootRateLimiter.class) +@ConditionalOnClass(MinBoxRateLimiter.class) @EnableConfigurationProperties(ApiBootRateLimiterProperties.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) @Import({ApiBootRateLimiterRedisAutoConfiguration.class, ApiBootRateLimiterNacosConfigConfiguration.class}) @@ -69,7 +69,7 @@ public ApiBootRateLimiterAutoConfiguration(ApiBootRateLimiterProperties apiBootR @Bean @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.redis.core.RedisTemplate") - public ApiBootRateLimiter googleGuavaRateLimiter(RateLimiterConfigCentre rateLimiterConfigCentre) { + public MinBoxRateLimiter googleGuavaRateLimiter(RateLimiterConfigCentre rateLimiterConfigCentre) { return new GoogleGuavaRateLimiter(apiBootRateLimiterProperties.isEnableGlobalQps() ? apiBootRateLimiterProperties.getGlobalQps() : 0L, rateLimiterConfigCentre); } @@ -88,13 +88,13 @@ public RateLimiterConfigCentre defaultRateLimiterConfigCentre() { /** * ApiBoot RateLimiter Pointcut Advisor * - * @param apiBootRateLimiterMethodInterceptor ResourceLoad Annotation Method Interceptor + * @param rateLimiterMethodInterceptor ResourceLoad Annotation Method Interceptor * @return ApiBootRateLimiterAdvisor */ @Bean @ConditionalOnMissingBean - ApiBootRateLimiterAdvisor rateLimiterAdvisor(ApiBootRateLimiterMethodInterceptor apiBootRateLimiterMethodInterceptor) { - return new ApiBootRateLimiterAdvisor(apiBootRateLimiterMethodInterceptor); + RateLimiterAdvisor rateLimiterAdvisor(RateLimiterMethodInterceptor rateLimiterMethodInterceptor) { + return new RateLimiterAdvisor(rateLimiterMethodInterceptor); } /** @@ -106,7 +106,7 @@ ApiBootRateLimiterAdvisor rateLimiterAdvisor(ApiBootRateLimiterMethodInterceptor */ @Bean @ConditionalOnMissingBean - ApiBootRateLimiterMethodInterceptor rateLimiterMethodInterceptor(ApiBootRateLimiter apiBootRateLimiter) { - return new ApiBootRateLimiterMethodInterceptor(apiBootRateLimiter, rateLimiterOverFlowResponse); + RateLimiterMethodInterceptor rateLimiterMethodInterceptor(MinBoxRateLimiter apiBootRateLimiter) { + return new RateLimiterMethodInterceptor(apiBootRateLimiter, rateLimiterOverFlowResponse); } } diff --git a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterNacosConfigConfiguration.java b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterNacosConfigConfiguration.java index 0cfed7cf..7367f50e 100644 --- a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterNacosConfigConfiguration.java +++ b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterNacosConfigConfiguration.java @@ -22,8 +22,8 @@ import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.exception.NacosException; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.minbox.framework.api.boot.limiter.centre.support.NacosRateLimiterConfigCentre; +import org.minbox.framework.limiter.centre.RateLimiterConfigCentre; +import org.minbox.framework.limiter.centre.support.NacosRateLimiterConfigCentre; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterRedisAutoConfiguration.java b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterRedisAutoConfiguration.java index 8156c528..d3de548b 100644 --- a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterRedisAutoConfiguration.java +++ b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/ratelimiter/ApiBootRateLimiterRedisAutoConfiguration.java @@ -16,9 +16,9 @@ */ package org.minbox.framework.api.boot.autoconfigure.ratelimiter; -import org.minbox.framework.api.boot.limiter.ApiBootRateLimiter; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.minbox.framework.api.boot.limiter.support.RedisLuaRateLimiter; +import org.minbox.framework.limiter.MinBoxRateLimiter; +import org.minbox.framework.limiter.centre.RateLimiterConfigCentre; +import org.minbox.framework.limiter.support.RedisLuaRateLimiter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -56,7 +56,7 @@ public ApiBootRateLimiterRedisAutoConfiguration(ApiBootRateLimiterProperties api */ @Bean @ConditionalOnMissingBean - public ApiBootRateLimiter redisLuaRateLimiter(RedisTemplate redisTemplate, RateLimiterConfigCentre rateLimiterConfigCentre) { + public MinBoxRateLimiter redisLuaRateLimiter(RedisTemplate redisTemplate, RateLimiterConfigCentre rateLimiterConfigCentre) { return new RedisLuaRateLimiter(apiBootRateLimiterProperties.isEnableGlobalQps() ? apiBootRateLimiterProperties.getGlobalQps() : 0L, rateLimiterConfigCentre, redisTemplate); } } diff --git a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/resource/ApiBootResourceLoadAutoConfiguration.java b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/resource/ApiBootResourceLoadAutoConfiguration.java index c814ba06..1147d189 100644 --- a/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/resource/ApiBootResourceLoadAutoConfiguration.java +++ b/api-boot-project/api-boot-autoconfigure/src/main/java/org/minbox/framework/api/boot/autoconfigure/resource/ApiBootResourceLoadAutoConfiguration.java @@ -16,11 +16,11 @@ */ package org.minbox.framework.api.boot.autoconfigure.resource; -import org.minbox.framework.api.boot.resource.ApiBootResourceStoreDelegate; -import org.minbox.framework.api.boot.resource.aop.advistor.ApiBootResourceLoadAdvisor; -import org.minbox.framework.api.boot.resource.aop.interceptor.ApiBootResourceLoadMethodInterceptor; -import org.minbox.framework.api.boot.resource.pusher.ApiBootResourcePusher; -import org.minbox.framework.api.boot.resource.pusher.support.ApiBootMemoryResourcePusher; +import org.minbox.framework.resource.ResourceStoreDelegate; +import org.minbox.framework.resource.aop.advistor.ResourceLoadAdvisor; +import org.minbox.framework.resource.aop.interceptor.ResourceLoadMethodInterceptor; +import org.minbox.framework.resource.pusher.ResourcePusher; +import org.minbox.framework.resource.pusher.support.MemoryResourcePusher; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -35,15 +35,15 @@ * @author 恒宇少年 */ @Configuration -@ConditionalOnClass(ApiBootResourceStoreDelegate.class) +@ConditionalOnClass(ResourceStoreDelegate.class) @Import(ApiBootResourceRedisLoadAutoConfiguration.class) public class ApiBootResourceLoadAutoConfiguration { /** * ApiBoot Resource Load Store Delegate */ - private ApiBootResourceStoreDelegate resourceStoreDelegate; + private ResourceStoreDelegate resourceStoreDelegate; - public ApiBootResourceLoadAutoConfiguration(ObjectProvider resourceStoreDelegateObjectProvider) { + public ApiBootResourceLoadAutoConfiguration(ObjectProvider resourceStoreDelegateObjectProvider) { this.resourceStoreDelegate = resourceStoreDelegateObjectProvider.getIfAvailable(); } @@ -55,8 +55,8 @@ public ApiBootResourceLoadAutoConfiguration(ObjectProvider resourceStoreDelegateObjectProvider) { + public ApiBootResourceRedisLoadAutoConfiguration(ObjectProvider resourceStoreDelegateObjectProvider) { this.resourceStoreDelegate = resourceStoreDelegateObjectProvider.getIfAvailable(); } @@ -54,7 +54,7 @@ public ApiBootResourceRedisLoadAutoConfiguration(ObjectProvider 1.0.5.RELEASE 1.0.5.RELEASE + 1.0.0.RELEASE + 1.0.0.RELEASE 1.0.0.RELEASE 1.0.5.RELEASE 1.1.3.RELEASE @@ -164,6 +166,16 @@ mybatis-enhance-dsl ${mybatis-enhance.version} + + org.minbox.framework + minbox-ratelimiter + ${minbox-ratelimiter.version} + + + org.minbox.framework + minbox-resource-load + ${minbox-resource-load.version} + diff --git a/api-boot-project/api-boot-starters/api-boot-starter-rate-limiter/pom.xml b/api-boot-project/api-boot-starters/api-boot-starter-rate-limiter/pom.xml index 01fbdb8f..9d4a98cf 100644 --- a/api-boot-project/api-boot-starters/api-boot-starter-rate-limiter/pom.xml +++ b/api-boot-project/api-boot-starters/api-boot-starter-rate-limiter/pom.xml @@ -49,6 +49,10 @@ org.minbox.framework api-boot-starter + + org.minbox.framework + minbox-ratelimiter + com.google.guava guava diff --git a/api-boot-project/api-boot-starters/api-boot-starter-resource-load/pom.xml b/api-boot-project/api-boot-starters/api-boot-starter-resource-load/pom.xml index 6024a22b..480ad494 100644 --- a/api-boot-project/api-boot-starters/api-boot-starter-resource-load/pom.xml +++ b/api-boot-project/api-boot-starters/api-boot-starter-resource-load/pom.xml @@ -50,6 +50,10 @@ org.minbox.framework api-boot-starter + + org.minbox.framework + minbox-resource-load + org.springframework.boot diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/ApiBootRateLimiter.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/ApiBootRateLimiter.java deleted file mode 100644 index a94fa78c..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/ApiBootRateLimiter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter; - -/** - * Definition of current limiting interface - *

- * a unified method for defining current limiting needs - *

- * Basic Abstract implementation class - * {@link org.minbox.framework.api.boot.limiter.support.AbstractRateLimiter} - *

- * Current restriction of token bucket mode of single application provided by Google - * {@link org.minbox.framework.api.boot.limiter.support.GoogleGuavaRateLimiter} - *

- * Implementation of redis Lua script for microservices and distributed applications - * {@link org.minbox.framework.api.boot.limiter.support.RedisLuaRateLimiter} - * - * @author 恒宇少年 - */ -public interface ApiBootRateLimiter { - /** - * Attempt to obtain a request current limit token - * - * @param QPS queries per second - * @param requestKey request key - * @return true : allow access to - */ - boolean tryAcquire(Double QPS, String requestKey); -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/annotation/RateLimiter.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/annotation/RateLimiter.java deleted file mode 100644 index eb0ccb23..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/annotation/RateLimiter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.annotation; - -import java.lang.annotation.*; - -/** - * ApiBoot Rate Limiter Annotation - * Configure to intercept request method - * - * @author 恒宇少年 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -@Documented -public @interface RateLimiter { - /** - * QPS(Access frequency per second) - * default once a second - * - * @return qps value - */ - double QPS() default 1; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/advisor/ApiBootRateLimiterAdvisor.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/advisor/ApiBootRateLimiterAdvisor.java deleted file mode 100644 index 76ac5117..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/advisor/ApiBootRateLimiterAdvisor.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.aop.advisor; - -import org.aopalliance.aop.Advice; -import org.minbox.framework.api.boot.limiter.annotation.RateLimiter; -import org.minbox.framework.api.boot.limiter.aop.interceptor.ApiBootRateLimiterMethodInterceptor; -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AbstractPointcutAdvisor; -import org.springframework.aop.support.ComposablePointcut; -import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.util.Assert; - -/** - * ApiBoot RateLimiter Advisor - * - * @author 恒宇少年 - */ -public class ApiBootRateLimiterAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { - /** - * method interceptor notification - * - * @see ApiBootRateLimiterMethodInterceptor - */ - private Advice advice; - /** - * breakthrough point - * {@link #buildPointcut()} - */ - private Pointcut pointcut; - /** - * Spring Bean Factory - * {@link BeanFactory} - */ - private BeanFactory beanFactory; - - public ApiBootRateLimiterAdvisor(ApiBootRateLimiterMethodInterceptor apiBootRateLimiterMethodInterceptor) { - // build pointcut instance - this.pointcut = buildPointcut(); - // build advice instance - this.advice = apiBootRateLimiterMethodInterceptor; - if (this.advice instanceof BeanFactoryAware) { - ((BeanFactoryAware) this.advice).setBeanFactory(beanFactory); - } - } - - @Override - public Pointcut getPointcut() { - Assert.notNull(this.pointcut, "pointcut is required."); - return this.pointcut; - } - - @Override - public Advice getAdvice() { - Assert.notNull(this.advice, "advice is required."); - return this.advice; - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - /** - * build breakthrough point - *

- * According to {@link RateLimiter} annotation pointcut - * - * @return {@link Pointcut} - */ - private Pointcut buildPointcut() { - // method - Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(RateLimiter.class); - return new ComposablePointcut(mpc); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/interceptor/ApiBootRateLimiterMethodInterceptor.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/interceptor/ApiBootRateLimiterMethodInterceptor.java deleted file mode 100644 index 5ada3636..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/aop/interceptor/ApiBootRateLimiterMethodInterceptor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.aop.interceptor; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.minbox.framework.api.boot.limiter.ApiBootRateLimiter; -import org.minbox.framework.api.boot.limiter.annotation.RateLimiter; -import org.minbox.framework.api.boot.limiter.result.RateLimiterOverFlowResponse; -import org.minbox.framework.api.boot.tools.AopTools; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.support.AopUtils; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; - -/** - * ApiBoot RateLimiter MethodInterceptor - * Current Limitation Request - * - * @author 恒宇少年 - */ -public class ApiBootRateLimiterMethodInterceptor implements MethodInterceptor { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(ApiBootRateLimiterMethodInterceptor.class); - /** - * ApiBoot RateLimiter - */ - private ApiBootRateLimiter apiBootRateLimiter; - /** - * Response results after flow exceeding - */ - private RateLimiterOverFlowResponse overFlowRequest; - - public ApiBootRateLimiterMethodInterceptor(ApiBootRateLimiter apiBootRateLimiter, RateLimiterOverFlowResponse overFlowRequest) { - this.apiBootRateLimiter = apiBootRateLimiter; - this.overFlowRequest = overFlowRequest; - Assert.notNull(apiBootRateLimiter, "No ApiBootRateLimiter implementation class instance."); - logger.info("ApiBootDefaultRateLimiterInterceptorHandler load complete."); - } - - /** - * Processing Current Limited Business Logic - * - * @param invocation method invocation - * @return method result - * @throws Throwable error instance - */ - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - try { - Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); - Method executeMethod = invocation.getMethod(); - - RateLimiter rateLimiter = AopTools.getMethodAnnotation(targetClass, executeMethod, RateLimiter.class); - - // request key - String requestKey = formatRequestKey(targetClass, executeMethod); - logger.debug("RateLimiter Request Key:{}", requestKey); - boolean acquire = apiBootRateLimiter.tryAcquire(rateLimiter.QPS(), requestKey); - if (acquire) { - return invocation.proceed(); - } - } catch (Exception e) { - logger.error("Current Limiting Request Encountered Exception.", e); - throw e; - } - // If an instance is created - if (!ObjectUtils.isEmpty(overFlowRequest)) { - return overFlowRequest.overflow(invocation.getArguments()); - } - return null; - } - - /** - * format request key - * - * @param targetClass target class - * @param executeMethod execute method - * @return request key - */ - private String formatRequestKey(Class targetClass, Method executeMethod) { - return String.format("%s#%s", targetClass.getName(), executeMethod.getName()); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/RateLimiterConfigCentre.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/RateLimiterConfigCentre.java deleted file mode 100644 index 2676b1ca..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/RateLimiterConfigCentre.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.centre; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; - -/** - * ApiBoot RateLimiter Distributed Configuration Center - * - * @author 恒宇少年 - */ -public interface RateLimiterConfigCentre { - /** - * Getting QPS from Configuration Center - * - * @param configKey config key - * @return QPS value - * @throws ApiBootException ApiBoot Exception - */ - Long getQps(String configKey) throws ApiBootException; - - /** - * QPS Setting to Configuration Center - * - * @param configKey config key - * @param QPS QPS value - * @throws ApiBootException ApiBoot Exception - */ - void setQps(String configKey, Long QPS) throws ApiBootException; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/AbstractRateLimiterConfigCentre.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/AbstractRateLimiterConfigCentre.java deleted file mode 100644 index 05d5fdbb..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/AbstractRateLimiterConfigCentre.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.centre.support; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.springframework.util.StringUtils; - -import java.io.IOException; -import java.io.StringReader; -import java.util.Enumeration; -import java.util.Properties; - -/** - * The {@link RateLimiterConfigCentre} abstract class - * - * @author 恒宇少年 - */ -public abstract class AbstractRateLimiterConfigCentre implements RateLimiterConfigCentre { - - /** - * data-id - */ - public static final String DATA_ID = "apiboot-rate-limiter-config"; - /** - * default qps - */ - public static final Long DEFAULT_QPS = 0L; - /** - * config properties key and value split - */ - public static final String PROPERTIES_KEY_VALUE_SPLIT = "="; - - /** - * data convert to properties - * - * @param content config data content - * @return Properties - */ - protected Properties toProperties(String content) throws ApiBootException { - try { - Properties properties = new Properties(); - if (!StringUtils.isEmpty(content)) { - properties.load(new StringReader(content)); - } - return properties; - } catch (IOException e) { - throw new ApiBootException(e.getMessage(), e); - } - } - - /** - * properties convert to string - * - * @param properties config properties - * @return config string - * @throws ApiBootException ApiBoot Exception - */ - protected String fromProperties(Properties properties) throws ApiBootException { - Enumeration enumeration = properties.propertyNames(); - StringBuffer buffer = new StringBuffer(); - while (enumeration.hasMoreElements()) { - String propertyKey = String.valueOf(enumeration.nextElement()); - String propertyValue = properties.getProperty(propertyKey); - buffer.append(propertyKey); - buffer.append(PROPERTIES_KEY_VALUE_SPLIT); - buffer.append(propertyValue); - buffer.append("\n"); - } - return buffer.toString(); - } - - /** - * format property key - * - * @param requestUri request uri - * @return property key - */ - protected String formatPropertyKey(String requestUri) { - return requestUri.replaceAll("/", "."); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/ApolloRateLimiterConfigCentre.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/ApolloRateLimiterConfigCentre.java deleted file mode 100644 index dbd54c97..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/ApolloRateLimiterConfigCentre.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.centre.support; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; - -/** - * The {@link RateLimiterConfigCentre} Apollo implementation class - * - * @author 恒宇少年 - */ -public class ApolloRateLimiterConfigCentre extends AbstractRateLimiterConfigCentre { - - @Override - public Long getQps(String configKey) throws ApiBootException { - return 0L; - } - - @Override - public void setQps(String configKey, Long QPS) throws ApiBootException { - - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/DefaultRateLimiterConfigCentre.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/DefaultRateLimiterConfigCentre.java deleted file mode 100644 index 7256c339..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/DefaultRateLimiterConfigCentre.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.centre.support; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; - -/** - * default rate limiter config centre - * - * @author 恒宇少年 - */ -public class DefaultRateLimiterConfigCentre extends AbstractRateLimiterConfigCentre { - @Override - public Long getQps(String configKey) throws ApiBootException { - return DEFAULT_QPS; - } - - @Override - public void setQps(String configKey, Long QPS) throws ApiBootException { - //... - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/NacosRateLimiterConfigCentre.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/NacosRateLimiterConfigCentre.java deleted file mode 100644 index 31ca2bc8..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/centre/support/NacosRateLimiterConfigCentre.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.centre.support; - -import com.alibaba.nacos.api.common.Constants; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.exception.NacosException; -import com.alibaba.nacos.client.config.listener.impl.PropertiesListener; -import com.alibaba.nacos.spring.util.NacosUtils; -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import java.util.Properties; - -/** - * Nacos Config Support - * The {@link RateLimiterConfigCentre} Nacos implement class - * - * @author 恒宇少年 - */ -public class NacosRateLimiterConfigCentre extends AbstractRateLimiterConfigCentre { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(NacosRateLimiterConfigCentre.class); - /** - * Nacos Config Service - */ - private ConfigService configService; - /** - * rate limiter config properties - */ - private Properties configProperties; - - public NacosRateLimiterConfigCentre(ConfigService configService) { - this.configService = configService; - - // check configService not null - Assert.notNull(configService, "ConfigService is required."); - - // load config data from nacos - String configData = loadConfigData(); - - // convert config data to properties - this.configProperties = toProperties(configData); - logger.info("ApiBoot RateLimiter nacos config properties load complete."); - - // Enable monitoring of receiving configuration changes - addConfigChangeListener(); - } - - /** - * get QPS config from nacos - * for example properties: - * 1. /user/list = .user.list: 5 - * 2. /user/detail = .user.detail: 10 - * - * @param configKey config key - * @return qps - * @throws ApiBootException ApiBoot Exception - */ - @Override - public Long getQps(String configKey) throws ApiBootException { - try { - String propertyKey = formatPropertyKey(configKey); - String qps = this.configProperties.getProperty(propertyKey); - if (!StringUtils.isEmpty(qps)) { - return Long.valueOf(qps); - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - return DEFAULT_QPS; - } - - /** - * set qps config to nacos - * - * @param configKey config key - * @param QPS QPS value - * @throws ApiBootException ApiBoot Exception - */ - @Override - public void setQps(String configKey, Long QPS) throws ApiBootException { - try { - String propertyKey = formatPropertyKey(configKey); - // update local cache config - this.configProperties.setProperty(propertyKey, String.valueOf(QPS)); - // convert properties to string - String configData = fromProperties(this.configProperties); - if (!StringUtils.isEmpty(configData)) { - // execute publish config - this.configService.publishConfig(DATA_ID, Constants.DEFAULT_GROUP, configData); - logger.info("ApiBoot RateLimiter nacos config publish successfully."); - } - } catch (Exception e) { - throw new ApiBootException(e.getMessage(), e); - } - } - - /** - * load rate limiter config data - * - * @return config data - * @throws ApiBootException ApiBoot Exception - */ - protected String loadConfigData() throws ApiBootException { - try { - return configService.getConfig(DATA_ID, Constants.DEFAULT_GROUP, NacosUtils.DEFAULT_TIMEOUT); - } catch (NacosException e) { - logger.error(e.getMessage(), e); - } - throw new ApiBootException("Load ApiBoot RateLimiter config data fail."); - } - - /** - * add config change listener - * If you modify the configuration through the nacos configuration center, - * listen to the changes and update the content Properties. - */ - protected void addConfigChangeListener() throws ApiBootException { - try { - configService.addListener(DATA_ID, Constants.DEFAULT_GROUP, new PropertiesListener() { - /** - * Update local properties - * @param properties Changed configuration properties - */ - @Override - public void innerReceive(Properties properties) { - configProperties = properties; - logger.info("Update local current RateLimiter configuration is complete,content:{}", properties.toString()); - } - }); - } catch (Exception e) { - logger.error("Configuration change listener failed to open.", e); - } - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/config/RateLimiterConfig.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/config/RateLimiterConfig.java deleted file mode 100644 index d2d28937..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/config/RateLimiterConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.config; - -import lombok.Data; - -/** - * ApiBoot RateLimiter Config - * - * @author 恒宇少年 - */ -@Data -public class RateLimiterConfig { - /** - * interceptor url prefix - */ - private String[] interceptorUrl; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/context/ApiBootRateLimiterContext.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/context/ApiBootRateLimiterContext.java deleted file mode 100644 index a9cebe95..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/context/ApiBootRateLimiterContext.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.context; - -import com.google.common.util.concurrent.RateLimiter; -import org.springframework.util.ObjectUtils; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * ApiBoot Rate Limiter Context - * - * @author 恒宇少年 - */ -public class ApiBootRateLimiterContext { - /** - * Cache a rateLimiter for each request address - */ - private static final ConcurrentMap RATE_LIMITER_MAP = new ConcurrentHashMap(); - - /** - * get rate limiter - * - * @param requestUri request uri - * @return RateLimiter - */ - public static RateLimiter getRateLimiter(String requestUri) { - return RATE_LIMITER_MAP.get(requestUri); - } - - /** - * cache request uri rate limiter - * - * @param requestUri request uri - * @param qps qps - * @return RateLimiter - */ - public static RateLimiter cacheRateLimiter(String requestUri, double qps) { - RateLimiter rateLimiter = getRateLimiter(requestUri); - if (ObjectUtils.isEmpty(rateLimiter)) { - rateLimiter = RateLimiter.create(qps); - RATE_LIMITER_MAP.put(requestUri, rateLimiter); - } - return rateLimiter; - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/result/RateLimiterOverFlowResponse.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/result/RateLimiterOverFlowResponse.java deleted file mode 100644 index de7dda8e..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/result/RateLimiterOverFlowResponse.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.result; - -/** - * Response results after flow exceeding - * - * @author 恒宇少年 - */ -@FunctionalInterface -public interface RateLimiterOverFlowResponse { - /** - * Response results after flow exceeding - * - * @param methodArgs request method args - * @return custom object - */ - Object overflow(Object[] methodArgs); -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/AbstractRateLimiter.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/AbstractRateLimiter.java deleted file mode 100644 index 07c3188f..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/AbstractRateLimiter.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.support; - -import org.minbox.framework.api.boot.limiter.ApiBootRateLimiter; -import org.minbox.framework.api.boot.limiter.centre.support.AbstractRateLimiterConfigCentre; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.springframework.util.ObjectUtils; - -/** - * ApiBoot RateLimiter Abstract Support - * - * @author 恒宇少年 - */ -public abstract class AbstractRateLimiter implements ApiBootRateLimiter { - /** - * global QPS - */ - private Long globalQPS; - /** - * ApiBoot RateLimiter Config Centre - */ - private RateLimiterConfigCentre rateLimiterConfigCentre; - - public AbstractRateLimiter(Long globalQPS, RateLimiterConfigCentre rateLimiterConfigCentre) { - this.globalQPS = globalQPS; - this.rateLimiterConfigCentre = rateLimiterConfigCentre; - } - - /** - * Priority to get QPS - * order - * first:Distributed configuration center(Nacos、Apollo) - * second:Annotation @RateLimiter QPS value - * third:GlobalQPS from application.yml(api.boot.rate-limiter.global-qps) - * - * @param configKey config key - * @param annotationQPS RateLimiter(QPS=xx) - * @return QPS value - */ - protected Long getPriorityQPS(String configKey, Double annotationQPS) { - // first:config centre value - Long centreConfigValue = rateLimiterConfigCentre.getQps(configKey); - if (!AbstractRateLimiterConfigCentre.DEFAULT_QPS.equals(centreConfigValue)) { - return centreConfigValue; - } - // If the configuration center does not have the qps of the key - // set qps to config centre - else { - rateLimiterConfigCentre.setQps(configKey, annotationQPS.longValue()); - } - // second:@RateLimiter value - if (!ObjectUtils.isEmpty(annotationQPS) && annotationQPS > 0) { - return annotationQPS.longValue(); - } - // third:global value - return globalQPS; - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/GoogleGuavaRateLimiter.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/GoogleGuavaRateLimiter.java deleted file mode 100644 index a52f10d5..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/GoogleGuavaRateLimiter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.support; - -import org.minbox.framework.api.boot.limiter.annotation.RateLimiter; -import org.minbox.framework.api.boot.limiter.context.ApiBootRateLimiterContext; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; - -/** - * Google guava rate limiter support - * - * @author 恒宇少年 - */ -public class GoogleGuavaRateLimiter extends AbstractRateLimiter { - public GoogleGuavaRateLimiter(Long globalQPS, RateLimiterConfigCentre rateLimiterConfigCentre) { - super(globalQPS, rateLimiterConfigCentre); - } - - /** - * google guava away - * - * @param annotationQPS {@link RateLimiter#QPS()} - * @param requestKey request key - * @return true : allow access to - */ - @Override - public boolean tryAcquire(Double annotationQPS, String requestKey) { - Long QPS = getPriorityQPS(requestKey, annotationQPS); - if (QPS <= 0) { - return true; - } - com.google.common.util.concurrent.RateLimiter rateLimiter = ApiBootRateLimiterContext.cacheRateLimiter(requestKey, QPS); - return rateLimiter.tryAcquire(); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/RedisLuaRateLimiter.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/RedisLuaRateLimiter.java deleted file mode 100644 index f6ec0977..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/limiter/support/RedisLuaRateLimiter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.limiter.support; - -import org.minbox.framework.api.boot.limiter.annotation.RateLimiter; -import org.minbox.framework.api.boot.limiter.centre.RateLimiterConfigCentre; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.ClassPathResource; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.data.redis.core.script.RedisScript; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import org.springframework.scripting.support.ResourceScriptSource; -import org.springframework.util.Assert; - -import java.time.Instant; -import java.util.Arrays; -import java.util.List; - -/** - * Redis lua rate limiter support - * - * @author 恒宇少年 - */ -public class RedisLuaRateLimiter extends AbstractRateLimiter { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(RedisLuaRateLimiter.class); - - /** - * Redis Script file name. - */ - private static final String QPS_LUA_PATH = "META-INF/scripts/qps-rate-limiter.lua"; - /** - * redis template - */ - private RedisTemplate redisTemplate; - /** - * Redis Script. - */ - private RedisScript> redisScript; - - public RedisLuaRateLimiter(Long globalQPS, RateLimiterConfigCentre rateLimiterConfigCentre, RedisTemplate redisTemplate) { - super(globalQPS, rateLimiterConfigCentre); - this.redisTemplate = redisTemplate; - this.redisScript = getRedisScript(); - - Assert.notNull(redisTemplate, "No RedisTemplate implementation class was found."); - Assert.notNull(redisScript, "Unable to load Lua script."); - } - - /** - * redis lua away - * Processing traffic restrictions using LUA scripts - * Processing with Spring Cloud Gateway official script - * - * @param annotationQPS {@link RateLimiter#QPS()} - * @param requestKey request key - * @return true : allow access to - */ - @Override - public boolean tryAcquire(Double annotationQPS, String requestKey) { - try { - Long QPS = getPriorityQPS(requestKey, annotationQPS); - if (QPS <= 0) { - return true; - } - // get keys - List keys = getKeys(requestKey); - - // Parameters and serialization of return values - RedisSerializer serializer = new StringRedisSerializer(); - - // execute lua script - List tokenResult = (List) this.redisTemplate.execute(this.redisScript, serializer, serializer, keys, String.valueOf(QPS), String.valueOf(QPS), Instant.now().getEpochSecond() + "", "1"); - - // Index 1 value is the number of remaining requestable tokens - Long newTokens = tokenResult.get(1); - if (logger.isDebugEnabled()) { - logger.debug("Number of remaining tokens for this request is {}", newTokens); - } - return newTokens > 0; - } catch (Exception e) { - /* - * We don't want a hard dependency on Redis to allow traffic. Make sure to set - * an alert so you know if this is happening too much. Stripe's observed - * failure rate is 0.01%. - */ - logger.error("Error determining if user allowed from redis", e); - } - return true; - } - - /** - * get Redis Script - * - * @return RedisScript - */ - RedisScript> getRedisScript() { - DefaultRedisScript redisScript = new DefaultRedisScript<>(); - redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(QPS_LUA_PATH))); - redisScript.setResultType(List.class); - return redisScript; - } - - /** - * get Keys - * - * @param id resource key(request uri) - * @return - */ - static List getKeys(String id) { - // use `{}` around keys to use Redis Key hash tags - // this allows for using redis cluster - - // Make a unique key per user. - String prefix = "qps_rate_limiter.{" + id; - - // You need two Redis keys for Token Bucket. - String tokenKey = prefix + "}.tokens"; - String timestampKey = prefix + "}.timestamp"; - return Arrays.asList(tokenKey, timestampKey); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/ApiBootResourceStoreDelegate.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/ApiBootResourceStoreDelegate.java deleted file mode 100644 index b35b78b6..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/ApiBootResourceStoreDelegate.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.minbox.framework.api.boot.resource; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; - -import java.util.List; - -/** - * ApiBoot Resource Load 数据驱动委托类 - * 该接口实现类用于查询资源信息 - * - * @author 恒宇少年 - */ -public interface ApiBootResourceStoreDelegate { - /** - * Load Resource Urls - * - * @param sourceFieldValue 资源所属业务字段的值 - * @param resourceType 资源类型 - * @return Resource urls - * @throws ApiBootException ApiBoot Exception - */ - List loadResourceUrl(String sourceFieldValue, String resourceType) throws ApiBootException; - - /** - * Add Resource Urls - * - * @param sourceFieldValue source field value - * @param resourceType resource type - * @param resourceUrls resource urls - * @throws ApiBootException ApiBoot Exception - */ - void addResource(String sourceFieldValue, String resourceType, List resourceUrls) throws ApiBootException; - - /** - * Delete resource urls - * - * @param sourceFieldValue source field value - * @param resourceType resource type - * @throws ApiBootException ApiBoot Exception - */ - void deleteResource(String sourceFieldValue, String resourceType) throws ApiBootException; - - /** - * Update resource urls - * - * @param sourceFieldValue source field value - * @param resourceType resource type - * @param resourceUrls resource urls - * @throws ApiBootException ApiBoot Exception - */ - void updateResource(String sourceFieldValue, String resourceType, List resourceUrls) throws ApiBootException; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceField.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceField.java deleted file mode 100644 index e48f7843..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceField.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.minbox.framework.api.boot.resource.annotation; - -import java.lang.annotation.*; - -/** - * 资源业务字段 - * 配置方法返回值资源字段的基本信息 - * - * @author 恒宇少年 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface ResourceField { - /** - * 资源加载后目标Field - * - * @return name - */ - String name(); - - /** - * 资源编号Field - * - * @return source - */ - String source(); - - /** - * 资源类型 - * 如:头像、封面图等 - * 由使用者定义 - * - * @return type - */ - String type(); - - /** - * 是否为数组 - * - * @return true:接收资源的字段为数组类型,false:非数组类型 - */ - boolean isArray() default false; - - /** - * 是否为list - * - * @return true:接收资源的字段为list类型,false:非list类型 - */ - boolean isList() default false; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceFields.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceFields.java deleted file mode 100644 index 5d5bdd03..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceFields.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.minbox.framework.api.boot.resource.annotation; - -import java.lang.annotation.*; - -/** - * 资源业务字段集合 - * - * @author 恒宇少年 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface ResourceFields { - /** - * 资源业务字段的集合 - * - * @return - */ - ResourceField[] value(); -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceLoad.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceLoad.java deleted file mode 100644 index 054bdf19..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/annotation/ResourceLoad.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.minbox.framework.api.boot.resource.annotation; - -import org.minbox.framework.api.boot.resource.enums.ResourceStoreEvent; - -import java.lang.annotation.*; - -/** - * 资源加载注解,该注解只能配置在方法上 - * - * @author 恒宇少年 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface ResourceLoad { - /** - * 资源存储事件 - * 默认查询资源 - * - * @return ResourceStoreEvent - */ - ResourceStoreEvent event() default ResourceStoreEvent.SELECT; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/advistor/ApiBootResourceLoadAdvisor.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/advistor/ApiBootResourceLoadAdvisor.java deleted file mode 100644 index 276796d7..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/advistor/ApiBootResourceLoadAdvisor.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.minbox.framework.api.boot.resource.aop.advistor; - -import org.aopalliance.aop.Advice; -import org.minbox.framework.api.boot.resource.annotation.ResourceLoad; -import org.minbox.framework.api.boot.resource.aop.interceptor.ApiBootResourceLoadMethodInterceptor; -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AbstractPointcutAdvisor; -import org.springframework.aop.support.ComposablePointcut; -import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.util.Assert; - -/** - * ApiBoot Resource Load Pointcut Advisor - * - * @author 恒宇少年 - */ -public class ApiBootResourceLoadAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { - - private Advice advice; - private Pointcut pointcut; - private BeanFactory beanFactory; - - public ApiBootResourceLoadAdvisor(ApiBootResourceLoadMethodInterceptor apiBootResourceLoadMethodInterceptor) { - // build pointcut instance - this.pointcut = buildPointcut(); - // build advice instance - this.advice = apiBootResourceLoadMethodInterceptor; - if (this.advice instanceof BeanFactoryAware) { - ((BeanFactoryAware) this.advice).setBeanFactory(beanFactory); - } - } - - @Override - public Pointcut getPointcut() { - Assert.notNull(this.pointcut, "pointcut is required."); - return this.pointcut; - } - - @Override - public Advice getAdvice() { - Assert.notNull(this.advice, "advice is required."); - return this.advice; - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - /** - * build pointcut instance - */ - private Pointcut buildPointcut() { - // method - Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(ResourceLoad.class); - return new ComposablePointcut(mpc); - } - -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/interceptor/ApiBootResourceLoadMethodInterceptor.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/interceptor/ApiBootResourceLoadMethodInterceptor.java deleted file mode 100644 index f3c008e9..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/aop/interceptor/ApiBootResourceLoadMethodInterceptor.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.minbox.framework.api.boot.resource.aop.interceptor; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.minbox.framework.api.boot.resource.annotation.ResourceLoad; -import org.minbox.framework.api.boot.resource.pusher.ApiBootResourcePusher; -import org.minbox.framework.api.boot.resource.enums.ResourceStoreEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.support.AopUtils; -import org.springframework.core.BridgeMethodResolver; -import org.springframework.util.ClassUtils; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; - -/** - * ApiBoot DataSource Advice - * use spring aop - * - * @author 恒宇少年 - */ -public class ApiBootResourceLoadMethodInterceptor implements MethodInterceptor { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(ApiBootResourceLoadMethodInterceptor.class); - - /** - * ApiBoot Resource Pusher - * Use to query resource url - */ - private ApiBootResourcePusher apiBootResourcePusher; - - public ApiBootResourceLoadMethodInterceptor(ApiBootResourcePusher apiBootResourcePusher) { - this.apiBootResourcePusher = apiBootResourcePusher; - } - - /** - * Execute method - * All event is after method execution query resource url - * - * @param invocation MethodInvocation - * @return Execute Result - * @throws Throwable method declared exception - * @see ResourceStoreEvent - */ - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); - Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass); - - // declared method object instance - Method declaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); - - // method param array - Object[] params = invocation.getArguments(); - - // execute method logic - Object result = invocation.proceed(); - // get resource Load - ResourceLoad resourceLoad = declaredMethod.getDeclaredAnnotation(ResourceLoad.class); - if (!ObjectUtils.isEmpty(resourceLoad)) { - switch (resourceLoad.event()) { - case SELECT: - logger.debug("Execute select resource."); - if (!ObjectUtils.isEmpty(result)) { - // resource push - apiBootResourcePusher.loadResource(declaredMethod, result); - } - break; - case INSERT: - logger.debug("Execute insert resource."); - // pull resource form param - apiBootResourcePusher.insertResource(declaredMethod, params); - break; - case DELETE: - logger.debug("Execute delete resource."); - apiBootResourcePusher.deleteResource(declaredMethod, params); - break; - case UPDATE: - logger.debug("Execute update resource."); - apiBootResourcePusher.updateResource(declaredMethod, params); - break; - default: - break; - } - } - return result; - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/context/ApiBootResourceContext.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/context/ApiBootResourceContext.java deleted file mode 100644 index 8131af92..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/context/ApiBootResourceContext.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.context; - -import org.minbox.framework.api.boot.resource.annotation.ResourceField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * ApiBoot Resource Context - * - * @author 恒宇少年 - */ -public class ApiBootResourceContext { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(ApiBootResourceContext.class); - - /** - * key -> method name - * value -> declared resource field annotation list - */ - private static ConcurrentMap> RESOURCE_FIELD_ANNOTATIONS = new ConcurrentHashMap(); - /** - * key -> method name - * value -> field instance - */ - private static ConcurrentMap RESOURCE_FIELDS = new ConcurrentHashMap(); - - /** - * get push field from cache - * - * @param declaredFieldClassName declared field class name - * @param fieldName field name - * @return Field - */ - public static Field getPushFieldFromCache(String declaredFieldClassName, String fieldName) { - String cacheKey = formatterCacheKey(declaredFieldClassName, fieldName); - logger.debug("Cache method [{}] push field from memory", cacheKey); - Field field = ApiBootResourceContext.RESOURCE_FIELDS.get(cacheKey); - return field; - } - - /** - * set push field to cache - * - * @param declaredFieldClassName declared field class name - * @param field push field - * @param fieldName field name - */ - public static void setPushFieldToCache(String declaredFieldClassName, String fieldName, Field field) { - String cacheKey = formatterCacheKey(declaredFieldClassName, fieldName); - logger.debug("Cache method [{}] push field to memory", cacheKey); - ApiBootResourceContext.RESOURCE_FIELDS.put(cacheKey, field); - } - - /** - * get method resource field from cache - * - * @param method method instance - * @return ResourceField list - */ - public static List getResourceFieldFromCache(Method method) { - String methodName = formatterMethodName(method); - logger.debug("Cache method [{}] resource field annotation from memory", methodName); - return ApiBootResourceContext.RESOURCE_FIELD_ANNOTATIONS.get(methodName); - } - - /** - * set method resource field to cache - * - * @param method method instance - * @param resourceFields method resource field annotation - */ - public static void setResourceFieldToCache(Method method, List resourceFields) { - String methodName = formatterMethodName(method); - logger.debug("Cache method [{}] resource field annotation to memory", methodName); - ApiBootResourceContext.RESOURCE_FIELD_ANNOTATIONS.put(methodName, resourceFields); - } - - /** - * formatter field cache key - * - * @param declaredFieldClassName declared file class name - * @param fieldName field name - * @return - */ - private static String formatterCacheKey(String declaredFieldClassName, String fieldName) { - String expression = "%s.%s"; - return String.format(expression, declaredFieldClassName, fieldName); - } - - /** - * formatter method name - * - * @param method method instance - * @return method name - */ - public static String formatterMethodName(Method method) { - String expression = "%s.%s"; - return String.format(expression, method.getDeclaringClass().getName(), method.getName()); - } - - /** - * formatter redis key - * - * @param method method instance - * @param sourceFieldValue source field value - * @param resourceType resource type - * @return redis key - */ - public static String formatterCacheKey(Method method, String sourceFieldValue, String resourceType) { - String expression = "%s.%s.%s"; - return String.format(expression, method.getDeclaringClass().getName(), resourceType, sourceFieldValue); - } -} - diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/enums/ResourceStoreEvent.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/enums/ResourceStoreEvent.java deleted file mode 100644 index 6116f9b5..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/enums/ResourceStoreEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.minbox.framework.api.boot.resource.enums; - -import lombok.Getter; - -/** - * 资源存储事件 - * - * @author 恒宇少年 - */ -@Getter -public enum ResourceStoreEvent { - /** - * 查询资源 - */ - SELECT, - /** - * 添加资源 - */ - INSERT, - /** - * 更新资源 - */ - UPDATE, - /** - * 删除资源 - */ - DELETE -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/expression/ResourceSourceExpression.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/expression/ResourceSourceExpression.java deleted file mode 100644 index 4d2abf91..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/expression/ResourceSourceExpression.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.expression; - -import org.minbox.framework.api.boot.resource.annotation.ResourceField; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * ApiBoot Resource Source Field Name Expression - * - * @author 恒宇少年 - */ -public class ResourceSourceExpression { - /** - * Source Name Basic Pattern - */ - static final Pattern SOURCE_NAME_PATTERN_BASIC = Pattern.compile("#p(\\d+)"); - /** - * Source Name Ognl Pattern - */ - static final Pattern SOURCE_NAME_PATTERN_OGNL = Pattern.compile("#p(\\d+).(\\S+)"); - - /** - * If match basic pattern - * - * @param sourceFieldName ResourceField annotation source value - * @return true: match , false: don't match - * @see ResourceField - */ - public static Matcher getBasicMatch(String sourceFieldName) { - Matcher matcher = SOURCE_NAME_PATTERN_BASIC.matcher(sourceFieldName); - return matcher; - } - - /** - * If match ognl pattern - * - * @param sourceFieldName ResourceField annotation source value - * @return true: match , false: don't match - * @see ResourceField - */ - public static Matcher getOgnlMatch(String sourceFieldName) { - Matcher matcher = SOURCE_NAME_PATTERN_OGNL.matcher(sourceFieldName); - return matcher; - } - - /** - * get match context list - * - * @param sourceFieldName ResourceField annotation source value - * @return match context list - */ - public static List getMatchContent(String sourceFieldName) { - List matchContents = new ArrayList<>(); - Matcher matcher = getOgnlMatch(sourceFieldName); - boolean isMatch = matcher.find(); - // If don't match ognl expression - if (!isMatch) { - // use basic expression - matcher = getBasicMatch(sourceFieldName); - isMatch = matcher.find(); - } - // If match basic expression - if (isMatch) { - // get all match value - for (int i = 1; i <= matcher.groupCount(); i++) { - matchContents.add(matcher.group(i)); - } - } - return matchContents; - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/loader/ResourceFieldLoader.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/loader/ResourceFieldLoader.java deleted file mode 100644 index a15f6924..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/loader/ResourceFieldLoader.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.loader; - -import org.minbox.framework.api.boot.resource.annotation.ResourceField; -import org.minbox.framework.api.boot.resource.annotation.ResourceFields; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * ApiBoot Resource Field Annotation Loader - * - * @author 恒宇少年 - */ -public class ResourceFieldLoader { - - /** - * load method declared ResourceField Annotation List - * - * @param method declared method - * @return ResourceField Annotation List - */ - public static List getDeclaredResourceField(Method method) { - List resourceFieldList = new ArrayList(); - // single ResourceField Annotation - ResourceField resourceField = method.getDeclaredAnnotation(ResourceField.class); - if (!ObjectUtils.isEmpty(resourceField)) { - resourceFieldList.add(resourceField); - } - - // multiple ResourceField Annotation - ResourceFields ResourceFields = method.getDeclaredAnnotation(ResourceFields.class); - if (!ObjectUtils.isEmpty(ResourceFields)) { - resourceFieldList.addAll(Arrays.asList(ResourceFields.value())); - } - - return resourceFieldList; - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/ApiBootResourcePusher.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/ApiBootResourcePusher.java deleted file mode 100644 index d7bc4eea..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/ApiBootResourcePusher.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.pusher; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.resource.pusher.support.ApiBootJdbcResourcePusher; -import org.minbox.framework.api.boot.resource.pusher.support.ApiBootRedisResourcePusher; - -import java.lang.reflect.Method; - -/** - * ApiBoot Resource Pusher Interface - * - * @author 恒宇少年 - * @see ApiBootJdbcResourcePusher - * @see ApiBootRedisResourcePusher - */ -public interface ApiBootResourcePusher { - /** - * Push resource to result field - * - * @param declaredMethod declared method - * @param methodExecuteResult method execute result - * @throws ApiBootException ApiBoot Exception - */ - void loadResource(Method declaredMethod, Object methodExecuteResult) throws ApiBootException; - - /** - * Pull resource from param - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - void insertResource(Method declaredMethod, Object[] param) throws ApiBootException; - - /** - * Delete resource - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - void deleteResource(Method declaredMethod, Object[] param) throws ApiBootException; - - /** - * Update resource - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - void updateResource(Method declaredMethod, Object[] param) throws ApiBootException; -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootAbstractResourcePusher.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootAbstractResourcePusher.java deleted file mode 100644 index eae84b32..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootAbstractResourcePusher.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.pusher.support; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.common.tools.ListTools; -import org.minbox.framework.api.boot.resource.annotation.ResourceField; -import org.minbox.framework.api.boot.resource.pusher.ApiBootResourcePusher; -import org.minbox.framework.api.boot.resource.tools.ResourceFieldTools; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; - -/** - * ApiBoot Resource Pusher Abstract Support - * Provide access to resource or source field - * - * @author 恒宇少年 - */ -public abstract class ApiBootAbstractResourcePusher implements ApiBootResourcePusher { - - /** - * load resource url - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @return resource list - */ - public abstract List loadResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType); - - /** - * delete resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - */ - public abstract void deleteResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType); - - /** - * insert resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - public abstract void insertResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls); - - /** - * update resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - public abstract void updateResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls); - - /** - * unified pull resource - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - @Override - public void insertResource(Method declaredMethod, Object[] param) throws ApiBootException { - // get method declared ResourceField annotations - List resourceFields = ResourceFieldTools.getResourceFields(declaredMethod); - resourceFields.stream().forEach(resourceField -> { - // get expression match source filed value - Object sourceFieldValue = ResourceFieldTools.getMatchSourceValue(resourceField.source(), param); - // get expression match resource field value - Object resourceFieldValue = ResourceFieldTools.getMatchResourceValue(resourceField.name(), param); - - // if have value - if (!ObjectUtils.isEmpty(sourceFieldValue) && !ObjectUtils.isEmpty(resourceFieldValue)) { - List resourceUrls = ListTools.convertToList(resourceFieldValue); - // call implementation class "deleteResourceUrl" method - this.insertResourceUrl(declaredMethod, String.valueOf(sourceFieldValue), resourceField.type(), resourceUrls); - } - }); - } - - /** - * unified delete resource - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - @Override - public void deleteResource(Method declaredMethod, Object[] param) throws ApiBootException { - // get method declared ResourceField annotations - List resourceFields = ResourceFieldTools.getResourceFields(declaredMethod); - resourceFields.stream().forEach(resourceField -> { - // get expression match source filed value - Object sourceFieldValue = ResourceFieldTools.getMatchSourceValue(resourceField.source(), param); - // if have value - if (!ObjectUtils.isEmpty(sourceFieldValue)) { - // call implementation class "deleteResourceUrl" method - this.deleteResourceUrl(declaredMethod, String.valueOf(sourceFieldValue), resourceField.type()); - } - }); - } - - /** - * unified update resource - * - * @param declaredMethod declared method - * @param param method param array - * @throws ApiBootException ApiBoot Exception - */ - @Override - public void updateResource(Method declaredMethod, Object[] param) throws ApiBootException { - // get method declared ResourceField annotations - List resourceFields = ResourceFieldTools.getResourceFields(declaredMethod); - resourceFields.stream().forEach(resourceField -> { - // get expression match source filed value - Object sourceFieldValue = ResourceFieldTools.getMatchSourceValue(resourceField.source(), param); - // get expression match resource field value - Object resourceFieldValue = ResourceFieldTools.getMatchResourceValue(resourceField.name(), param); - // if have value - if (!ObjectUtils.isEmpty(sourceFieldValue) && !ObjectUtils.isEmpty(resourceFieldValue)) { - List resourceUrls = ListTools.convertToList(resourceFieldValue); - // call implementation class "insertResourceUrl" method - this.updateResourceUrl(declaredMethod, String.valueOf(sourceFieldValue), resourceField.type(), resourceUrls); - } - }); - } - - /** - * unified push resource - * - * @param method method - * @param result method execute result - */ - @Override - public void loadResource(Method method, Object result) { - // list - if (result instanceof List) { - pushToList(method, (List) result); - } - // map - else if (result instanceof Map) { - pushToMap(method, (Map) result); - } - // result is mybatis pageable - /*else if (result instanceof Page) { - Page page = (Page) result; - pushToList(method, page.getData()); - }*/ - // single - else if (result instanceof Object) { - pushToObject(method, result); - } - } - - /** - * push resource url to list result - * - * @param method method - * @param executeResultList method execute result list - * @throws Exception Exception - */ - private void pushToList(Method method, List executeResultList) { - List resourceFields = ResourceFieldTools.getResourceFields(method); - executeResultList.stream().forEach(o -> push(method, resourceFields, o)); - } - - /** - * push resource url to map result - * - * @param method method - * @param executeResultMap method execute result map - * @throws Exception Exception - */ - private void pushToMap(Method method, Map executeResultMap) { - List resourceFields = ResourceFieldTools.getResourceFields(method); - executeResultMap.keySet().stream().forEach(o -> push(method, resourceFields, executeResultMap.get(o))); - } - - /** - * push resource url to result object - * - * @param method method - * @param executeResult method execute result object - */ - private void pushToObject(Method method, Object executeResult) { - List resourceFields = ResourceFieldTools.getResourceFields(method); - push(method, resourceFields, executeResult); - } - - /** - * execute push - * - * @param resourceFields ResourceField Annotation List - * @param object single object - */ - private void push(Method method, List resourceFields, Object object) { - Class objectClass = object.getClass(); - resourceFields.stream().forEach(resourceField -> { - try { - // source - Field sourceField = ResourceFieldTools.getField(objectClass, resourceField.source()); - // target - Field resourceFieldInstance = ResourceFieldTools.getField(objectClass, resourceField.name()); - - // get source filed value - Object sourceFieldValue = sourceField.get(object); - // load resource urls - List resourceUrls = loadResourceUrl(method, String.valueOf(sourceFieldValue), resourceField.type()); - - if (!ObjectUtils.isEmpty(resourceUrls)) { - // resource field is array - if (resourceField.isArray()) { - resourceFieldInstance.set(object, resourceUrls.toArray()); - } - // resource field is list - else if (resourceField.isList()) { - resourceFieldInstance.set(object, resourceUrls); - } - // resource field is single string - else { - resourceFieldInstance.set(object, resourceUrls.get(0)); - } - } - } catch (Exception e) { - throw new ApiBootException("Push resource fail.", e); - } - - }); - - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootJdbcResourcePusher.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootJdbcResourcePusher.java deleted file mode 100644 index b4f7b7d4..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootJdbcResourcePusher.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.pusher.support; - -import org.minbox.framework.api.boot.common.exception.ApiBootException; -import org.minbox.framework.api.boot.resource.ApiBootResourceStoreDelegate; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; -import java.util.List; - -/** - * ApiBoot Jdbc Resource Pusher - * - * @author 恒宇少年 - */ -public class ApiBootJdbcResourcePusher extends ApiBootAbstractResourcePusher { - /** - * ApiBoot Resource Store Delegate - * Use load resource url from jdbc - */ - private ApiBootResourceStoreDelegate apiBootResourceStoreDelegate; - - public ApiBootJdbcResourcePusher(ApiBootResourceStoreDelegate apiBootResourceStoreDelegate) { - this.apiBootResourceStoreDelegate = apiBootResourceStoreDelegate; - if (ObjectUtils.isEmpty(this.apiBootResourceStoreDelegate)) { - throw new ApiBootException("Unable to load [ApiBootResourceStoreDelegate] implementation class instance"); - } - } - - /** - * load resource from ApiBootResourceStoreDelegate#loadResourceUrl method - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @return resource List - * @see ApiBootResourceStoreDelegate - */ - @Override - public List loadResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - return apiBootResourceStoreDelegate.loadResourceUrl(sourceFieldValue, resourceType); - } - - /** - * delete resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - */ - @Override - public void deleteResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - apiBootResourceStoreDelegate.deleteResource(sourceFieldValue, resourceType); - } - - /** - * insert resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void insertResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - apiBootResourceStoreDelegate.addResource(sourceFieldValue, resourceType, resourceUrls); - } - - /** - * update resource urls - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void updateResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - apiBootResourceStoreDelegate.updateResource(sourceFieldValue, resourceType, resourceUrls); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootMemoryResourcePusher.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootMemoryResourcePusher.java deleted file mode 100644 index 8f45aae8..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootMemoryResourcePusher.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.pusher.support; - -import org.minbox.framework.api.boot.resource.ApiBootResourceStoreDelegate; -import org.minbox.framework.api.boot.resource.context.ApiBootResourceContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * ApiBoot Resource Memory Pusher - * - * @author 恒宇少年 - */ -public class ApiBootMemoryResourcePusher extends ApiBootJdbcResourcePusher { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(ApiBootMemoryResourcePusher.class); - /** - * memory resource urls - */ - private Map> RESOURCE_URLS = new HashMap(); - - public ApiBootMemoryResourcePusher(ApiBootResourceStoreDelegate apiBootResourceStoreDelegate) { - super(apiBootResourceStoreDelegate); - } - - /** - * Check whether the data is cached in memory - * If not cached, query from the database - * If cached , query from the memory - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @return resource urls - */ - @Override - public List loadResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, load resource urls with memory fail."); - return Collections.emptyList(); - } - // formatter key - String resourceKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - // get resource urls - List resourceUrls = RESOURCE_URLS.get(resourceKey); - if (ObjectUtils.isEmpty(resourceUrls)) { - // get resource urls from jdbc - resourceUrls = super.loadResourceUrl(declaredMethod, sourceFieldValue, resourceType); - // put resource - RESOURCE_URLS.put(resourceKey, resourceUrls); - } - return resourceUrls; - } - - /** - * remove from memory - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - */ - @Override - public void deleteResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, delete resource urls with memory fail."); - return; - } - // remove from jdbc - super.deleteResourceUrl(declaredMethod, sourceFieldValue, resourceType); - // formatter key - String resourceKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - // remove memory resource urls - RESOURCE_URLS.remove(resourceKey); - } - - /** - * insert to memory - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void insertResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType) || ObjectUtils.isEmpty(resourceUrls)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, insert resource urls with memory fail."); - return; - } - super.insertResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - // formatter key - String resourceKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - // remove memory resource urls - RESOURCE_URLS.put(resourceKey, resourceUrls); - } - - /** - * update memory data - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void updateResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType) || ObjectUtils.isEmpty(resourceUrls)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, update resource urls with memory fail."); - return; - } - super.updateResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - - // execute delete resource urls - deleteResourceUrl(declaredMethod, sourceFieldValue, resourceType); - - // execute insert resource urls - insertResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootRedisResourcePusher.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootRedisResourcePusher.java deleted file mode 100644 index 6a13a50f..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/pusher/support/ApiBootRedisResourcePusher.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.pusher.support; - -import org.minbox.framework.api.boot.resource.ApiBootResourceStoreDelegate; -import org.minbox.framework.api.boot.resource.context.ApiBootResourceContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.util.ObjectUtils; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; - -/** - * ApiBoot Redis Resource Pusher - * - * @author 恒宇少年 - */ -public class ApiBootRedisResourcePusher extends ApiBootJdbcResourcePusher { - /** - * logger instance - */ - static Logger logger = LoggerFactory.getLogger(ApiBootRedisResourcePusher.class); - - /** - * Redis Template - */ - private RedisTemplate redisTemplate; - - public ApiBootRedisResourcePusher(ApiBootResourceStoreDelegate apiBootResourceStoreDelegate, RedisTemplate redisTemplate) { - super(apiBootResourceStoreDelegate); - this.redisTemplate = redisTemplate; - } - - /** - * Check whether the data is cached in redis - * If not cached, query from the database - * If cached , query from the redis - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @return resource urls - */ - @Override - public List loadResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, load resource urls with redis fail."); - return Collections.emptyList(); - } - // formatter redis key - String resourceRedisKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - // get resource size - long resourceSize = redisTemplate.opsForList().size(resourceRedisKey); - if (resourceSize <= 0) { - // load resource url from jdbc - List resourceUrls = super.loadResourceUrl(declaredMethod, sourceFieldValue, resourceType); - // push resource urls to redis - redisTemplate.opsForList().rightPushAll(resourceRedisKey, resourceUrls); - } - // pull all resource urls from redis - return redisTemplate.opsForList().range(resourceRedisKey, 0, -1); - } - - /** - * delete resource from redis - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - */ - @Override - public void deleteResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, delete resource urls with redis fail."); - return; - } - // formatter redis key - String resourceRedisKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - - // execute delete redis resource - redisTemplate.delete(resourceRedisKey); - - // delete from jdbc - super.deleteResourceUrl(declaredMethod, sourceFieldValue, resourceType); - } - - /** - * insert into redis - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void insertResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType) || ObjectUtils.isEmpty(resourceUrls)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, insert resource urls with redis fail."); - return; - } - super.insertResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - // formatter redis key - String resourceRedisKey = ApiBootResourceContext.formatterCacheKey(declaredMethod, sourceFieldValue, resourceType); - // push resource urls to redis - redisTemplate.opsForList().rightPushAll(resourceRedisKey, resourceUrls); - } - - /** - * update redis resource data - * - * @param declaredMethod declared method - * @param sourceFieldValue sourceFieldValue - * @param resourceType resourceType - * @param resourceUrls resource urls - */ - @Override - public void updateResourceUrl(Method declaredMethod, String sourceFieldValue, String resourceType, List resourceUrls) { - if (ObjectUtils.isEmpty(sourceFieldValue) || ObjectUtils.isEmpty(resourceType) || ObjectUtils.isEmpty(resourceUrls)) { - logger.warn("@ResourceField param [source]|[type]|[name] have empty value, update resource urls with redis fail."); - return; - } - super.updateResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - - // execute delete redis data - deleteResourceUrl(declaredMethod, sourceFieldValue, resourceType); - - // execute insert redis data - insertResourceUrl(declaredMethod, sourceFieldValue, resourceType, resourceUrls); - } -} diff --git a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/tools/ResourceFieldTools.java b/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/tools/ResourceFieldTools.java deleted file mode 100644 index c59bbcdd..00000000 --- a/api-boot-project/api-boot/src/main/java/org/minbox/framework/api/boot/resource/tools/ResourceFieldTools.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright [2019] [恒宇少年 - 于起宇] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.minbox.framework.api.boot.resource.tools; - -import org.minbox.framework.api.boot.resource.annotation.ResourceField; -import org.minbox.framework.api.boot.resource.context.ApiBootResourceContext; -import org.minbox.framework.api.boot.resource.expression.ResourceSourceExpression; -import org.minbox.framework.api.boot.resource.loader.ResourceFieldLoader; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; - -/** - * Resource Tools - * - * @author 恒宇少年 - */ -public class ResourceFieldTools { - /** - * Get expression match value - * - * @param matchFieldName match field name - * @param param method param - * @return match value - */ - public static Object getMatchValue(String matchFieldName, Object[] param) { - // pattern expression match contents - List matchContents = ResourceSourceExpression.getMatchContent(matchFieldName); - - // source field value - Object sourceFieldValue = null; - - // don't match expression - // default parameters using index 0 - if (ObjectUtils.isEmpty(matchContents)) { - Object paramObject = param[0]; - // source field - Field field = getField(paramObject.getClass(), matchFieldName); - // source field value - sourceFieldValue = getFieldValue(field, paramObject); - } - // match expression - else { - // ognl expression - if (ResourceSourceExpression.getOgnlMatch(matchFieldName).find()) { - // param object - Object paramObject = param[Integer.valueOf(matchContents.get(0))]; - // source field - Field field = getField(paramObject.getClass(), matchContents.get(1)); - // source field value - sourceFieldValue = getFieldValue(field, paramObject); - } - // basic expression - else if (ResourceSourceExpression.getBasicMatch(matchFieldName).find()) { - sourceFieldValue = param[Integer.valueOf(matchContents.get(0))]; - } - } - return sourceFieldValue; - } - - /** - * Get expression match resource field value - * - * @param resourceFieldName ResourceField Annotation name - * @param param method param array - * @return resource field value - */ - public static Object getMatchResourceValue(String resourceFieldName, Object[] param) { - return getMatchValue(resourceFieldName, param); - } - - /** - * Get expression match source field value - * - * @param sourceFieldName ResourceField Annotation source - * @param param method param array - * @return source field value - */ - public static Object getMatchSourceValue(String sourceFieldName, Object[] param) { - return getMatchValue(sourceFieldName, param); - } - - /** - * get Field value - * - * @param field field instance - * @param object field subordinate object - * @return Field value - */ - public static Object getFieldValue(Field field, Object object) { - try { - if (!field.isAccessible()) { - field.setAccessible(true); - } - return field.get(object); - } catch (Exception e) { - return null; - } - } - - /** - * get field instance - * - * @param objectClass method result object class - * @param fieldName field name - * @return Field Instance - */ - public static Field getField(Class objectClass, String fieldName) { - // cache from memory - Field sourceField = ApiBootResourceContext.getPushFieldFromCache(objectClass.getName(), fieldName); - // if don't have source field from cache - if (ObjectUtils.isEmpty(sourceField)) { - sourceField = ReflectionUtils.findField(objectClass, fieldName); - if (!sourceField.isAccessible()) { - sourceField.setAccessible(true); - } - // cache to memory - ApiBootResourceContext.setPushFieldToCache(objectClass.getName(), fieldName, sourceField); - } - return sourceField; - } - - /** - * Load method declared ResourceField Annotations - * - * @param method method - * @return ResourceField List - */ - private static List loadMethodResourceFields(Method method) { - // load method declared ResourceField Annotation List - List resourceFields = ResourceFieldLoader.getDeclaredResourceField(method); - return resourceFields; - } - - /** - * get method declared resource field annotation - * 1. get from cache - * 2. loading from method declared - * - * @param method method - * @return List ResourceField - */ - public static List getResourceFields(Method method) { - // get from cache - List resourceFields = ApiBootResourceContext.getResourceFieldFromCache(method); - - // loading from method declared - if (ObjectUtils.isEmpty(resourceFields)) { - resourceFields = loadMethodResourceFields(method); - // set to cache - ApiBootResourceContext.setResourceFieldToCache(method, resourceFields); - } - return resourceFields; - } -} diff --git a/api-boot-project/api-boot/src/main/resources/META-INF/scripts/qps-rate-limiter.lua b/api-boot-project/api-boot/src/main/resources/META-INF/scripts/qps-rate-limiter.lua deleted file mode 100644 index ee7a7334..00000000 --- a/api-boot-project/api-boot/src/main/resources/META-INF/scripts/qps-rate-limiter.lua +++ /dev/null @@ -1,50 +0,0 @@ -local tokens_key = KEYS[1] -local timestamp_key = KEYS[2] ---redis.log(redis.LOG_WARNING, "tokens_key " .. tokens_key) - -local rate = tonumber(ARGV[1]) -local capacity = tonumber(ARGV[2]) -local now = tonumber(ARGV[3]) -local requested = tonumber(ARGV[4]) - -local fill_time = capacity/rate -local ttl = math.floor(fill_time*2) - ---redis.log(redis.LOG_WARNING, "rate " .. ARGV[1]) ---redis.log(redis.LOG_WARNING, "capacity " .. ARGV[2]) ---redis.log(redis.LOG_WARNING, "now " .. ARGV[3]) ---redis.log(redis.LOG_WARNING, "requested " .. ARGV[4]) ---redis.log(redis.LOG_WARNING, "filltime " .. fill_time) ---redis.log(redis.LOG_WARNING, "ttl " .. ttl) - -local last_tokens = tonumber(redis.call("get", tokens_key)) -if last_tokens == nil then - last_tokens = capacity -end ---redis.log(redis.LOG_WARNING, "last_tokens " .. last_tokens) - -local last_refreshed = tonumber(redis.call("get", timestamp_key)) -if last_refreshed == nil then - last_refreshed = 0 -end ---redis.log(redis.LOG_WARNING, "last_refreshed " .. last_refreshed) - -local delta = math.max(0, now-last_refreshed) -local filled_tokens = math.min(capacity, last_tokens+(delta*rate)) -local allowed = filled_tokens >= requested -local new_tokens = filled_tokens -local allowed_num = 0 -if allowed then - new_tokens = filled_tokens - requested - allowed_num = 1 -end - ---redis.log(redis.LOG_WARNING, "delta " .. delta) ---redis.log(redis.LOG_WARNING, "filled_tokens " .. filled_tokens) ---redis.log(redis.LOG_WARNING, "allowed_num " .. allowed_num) ---redis.log(redis.LOG_WARNING, "new_tokens " .. new_tokens) - -redis.call("setex", tokens_key, ttl, new_tokens) -redis.call("setex", timestamp_key, ttl, now) - -return { allowed_num, new_tokens } diff --git a/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/CustomerResponse.java b/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/CustomerResponse.java index be845b95..47f3ebef 100644 --- a/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/CustomerResponse.java +++ b/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/CustomerResponse.java @@ -18,7 +18,7 @@ package org.minbox.framework.api.boot.sample; import org.minbox.framework.api.boot.common.model.ApiBootResult; -import org.minbox.framework.api.boot.limiter.result.RateLimiterOverFlowResponse; +import org.minbox.framework.limiter.result.RateLimiterOverFlowResponse; import org.springframework.stereotype.Component; /** diff --git a/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/RateLimiterSampleController.java b/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/RateLimiterSampleController.java index a77df494..4ed4f272 100644 --- a/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/RateLimiterSampleController.java +++ b/api-boot-samples/api-boot-sample-rate-limiter/src/main/java/org/minbox/framework/api/boot/sample/RateLimiterSampleController.java @@ -17,7 +17,7 @@ package org.minbox.framework.api.boot.sample; -import org.minbox.framework.api.boot.limiter.annotation.RateLimiter; +import org.minbox.framework.limiter.annotation.RateLimiter; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;