diff --git a/src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountService.java b/src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountService.java new file mode 100644 index 0000000000000000000000000000000000000000..ccab7c44efe37a9c3c626987dd8d7727b7439680 --- /dev/null +++ b/src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountService.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.module.framework.restful.counter; + +public interface ApiAccessCountService { + + void putToken(String token); +} diff --git a/src/main/java/neatlogic/framework/restful/counter/ApiAccessCountManager.java b/src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountServiceImpl.java similarity index 81% rename from src/main/java/neatlogic/framework/restful/counter/ApiAccessCountManager.java rename to src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountServiceImpl.java index bfff664188d624ae5673b7457aeeb48a34e1a09e..d92bb18166cff79e1e903487d12edc4631331a76 100644 --- a/src/main/java/neatlogic/framework/restful/counter/ApiAccessCountManager.java +++ b/src/main/java/neatlogic/module/framework/restful/counter/ApiAccessCountServiceImpl.java @@ -1,19 +1,21 @@ -/*Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see .*/ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ -package neatlogic.framework.restful.counter; +package neatlogic.module.framework.restful.counter; import neatlogic.framework.asynchronization.thread.NeatLogicThread; import neatlogic.framework.asynchronization.threadlocal.TenantContext; @@ -22,20 +24,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.DelayQueue; import java.util.concurrent.atomic.AtomicLong; -/** - * @ClassName: ApiAccessCountManager - * @Description: 接口访问次数统计管理类 - */ @Service -public class ApiAccessCountManager { +public class ApiAccessCountServiceImpl implements ApiAccessCountService { - private static final Logger logger = LoggerFactory.getLogger(ApiAccessCountManager.class); + private static final Logger logger = LoggerFactory.getLogger(ApiAccessCountServiceImpl.class); /** * 统计延迟对象,默认初始化一个失效的延迟对象 **/ @@ -45,9 +44,12 @@ public class ApiAccessCountManager { **/ private static final DelayQueue delayQueue = new DelayQueue<>(); - private static ApiAuditMapper apiAuditMapper; + @Resource + private ApiAuditMapper apiAuditMapper; + - static { + @PostConstruct + public void init() { Thread t = new Thread(new NeatLogicThread("API-ACCESS-COUNT-MANAGER") { @Override @@ -123,27 +125,19 @@ public class ApiAccessCountManager { t.start(); } - @Resource - public void setApiAuditMapper(ApiAuditMapper _apiAuditMapper) { - apiAuditMapper = _apiAuditMapper; - } - - - public static void putToken(String token) { + @Override + public void putToken(String token) { try { /* 判断延迟对象是否失效 **/ - if (delayedItem.isExpired()) { + if (!delayedItem.putToken(token)) { // Thread.sleep(1);//测试时使用 /* 初始化延迟对象时,必须加锁,否则会出现多个线程相互覆盖情况 **/ - synchronized (ApiAccessCountManager.class) { + synchronized (this) { if (delayedItem.isExpired()) { delayedItem = new DelayedItem(); delayQueue.add(delayedItem); } } -// Thread.sleep(1);//测试时使用 - putToken(token); - } else { // Thread.sleep(1);//测试时使用 delayedItem.putToken(token); } diff --git a/src/main/java/neatlogic/framework/restful/counter/DelayedItem.java b/src/main/java/neatlogic/module/framework/restful/counter/DelayedItem.java similarity index 74% rename from src/main/java/neatlogic/framework/restful/counter/DelayedItem.java rename to src/main/java/neatlogic/module/framework/restful/counter/DelayedItem.java index 90a355ba134e13c581922fe0e931c2244993139a..7229b29ed1cce0c06857ed463e8d8abd082c584b 100644 --- a/src/main/java/neatlogic/framework/restful/counter/DelayedItem.java +++ b/src/main/java/neatlogic/module/framework/restful/counter/DelayedItem.java @@ -1,19 +1,21 @@ -/*Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see .*/ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ -package neatlogic.framework.restful.counter; +package neatlogic.module.framework.restful.counter; import neatlogic.framework.asynchronization.threadlocal.TenantContext; import org.slf4j.Logger; @@ -77,16 +79,14 @@ public class DelayedItem implements Delayed { return delayTime - System.currentTimeMillis(); } - public void putToken(String token) { - try { - /* 写数据前加1**/ - writingDataThreadNum.incrementAndGet(); -// Thread.sleep(1);//测试时使用 - /* 判断延迟对象是否失效 **/ - if(expired.get()) { + public boolean putToken(String token) { + if(expired.get()) { + return false; + }else { + try { + /* 写数据前加1**/ + writingDataThreadNum.incrementAndGet(); // Thread.sleep(1);//测试时使用 - ApiAccessCountManager.putToken(token); - }else { String tenantUuid = TenantContext.get().getTenantUuid(); /* 从缓存中获取当前租户访问记录 **/ ConcurrentMap accessTokenCounterMap = tenantAccessTokenMap.get(tenantUuid); @@ -117,34 +117,35 @@ public class DelayedItem implements Delayed { // Thread.sleep(1);//测试时使用 counter.incrementAndGet(); } - } - - }catch(Exception e) { - logger.error(e.getMessage(), e); - }finally { + + }catch(Exception e) { + logger.error(e.getMessage(), e); + }finally { // try { // Thread.sleep(1);//测试时使用 // } catch (InterruptedException e) { // e.printStackTrace(); // } - if(writingDataThreadNum.decrementAndGet() <= 0) { + if(writingDataThreadNum.decrementAndGet() <= 0) { // try { // Thread.sleep(1);//测试时使用 // } catch (InterruptedException e) { // e.printStackTrace(); // } - if(expired.get()) { + if(expired.get()) { // try { // Thread.sleep(1);//测试时使用 // } catch (InterruptedException e) { // e.printStackTrace(); // } - /* 如果当前延迟对象已失效且没有线程往延迟对象写数据,就唤醒lock对象monitor的wait set中的线程,只有一个 **/ - synchronized(lock) { - lock.notify(); + /* 如果当前延迟对象已失效且没有线程往延迟对象写数据,就唤醒lock对象monitor的wait set中的线程,只有一个 **/ + synchronized(lock) { + lock.notify(); + } } } - } + } + return true; } } diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java index 3b7f1c52363a59684d0d4592282fb077d5db266b..ddcd1d9bf2eaf4ecdadd2b74c3c653b7c2b6c55e 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java @@ -38,7 +38,6 @@ import neatlogic.framework.restful.core.IBinaryStreamApiComponent; import neatlogic.framework.restful.core.IJsonStreamApiComponent; import neatlogic.framework.restful.core.IRawApiComponent; import neatlogic.framework.restful.core.privateapi.PrivateApiComponentFactory; -import neatlogic.framework.restful.counter.ApiAccessCountManager; import neatlogic.framework.restful.dao.mapper.ApiLongCacheMapper; import neatlogic.framework.restful.dto.ApiHandlerVo; import neatlogic.framework.restful.dto.ApiVo; @@ -46,6 +45,7 @@ import neatlogic.framework.restful.enums.ApiType; import neatlogic.framework.restful.ratelimiter.RateLimiterTokenBucket; import neatlogic.framework.util.$; import neatlogic.framework.util.AnonymousApiTokenUtil; +import neatlogic.module.framework.restful.counter.ApiAccessCountService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -76,6 +76,9 @@ public class AnonymousApiDispatcher { @Resource private ApiLongCacheMapper apiLongCacheMapper; + @Resource + private ApiAccessCountService apiAccessCountService; + private void doIt(HttpServletRequest request, HttpServletResponse response, String token, boolean tokenHasEncrypted, ApiType apiType, JSONObject paramObj, JSONObject returnObj, String action) throws Exception { ApiVo interfaceVo = PrivateApiComponentFactory.getApiByToken(token); RequestContext.init(request, token, response); @@ -136,7 +139,7 @@ public class AnonymousApiDispatcher { } if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long startTime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, response); Long endTime = System.currentTimeMillis(); @@ -163,7 +166,7 @@ public class AnonymousApiDispatcher { } if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, new JSONReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8))); Long endtime = System.currentTimeMillis(); @@ -190,7 +193,7 @@ public class AnonymousApiDispatcher { } if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, request, response); Long endtime = System.currentTimeMillis(); @@ -217,7 +220,7 @@ public class AnonymousApiDispatcher { } if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj.getString("payload"), response); Long endtime = System.currentTimeMillis(); diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java index 071f0c5970a1ff20ab226b2fdaf0938d31d78878..79960d3425194212cc3e6c9cabbfe7c78aa78c14 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java @@ -36,7 +36,6 @@ import neatlogic.framework.restful.core.IBinaryStreamApiComponent; import neatlogic.framework.restful.core.IJsonStreamApiComponent; import neatlogic.framework.restful.core.IRawApiComponent; import neatlogic.framework.restful.core.privateapi.PrivateApiComponentFactory; -import neatlogic.framework.restful.counter.ApiAccessCountManager; import neatlogic.framework.restful.dao.mapper.ApiLongCacheMapper; import neatlogic.framework.restful.dto.ApiHandlerVo; import neatlogic.framework.restful.dto.ApiVo; @@ -45,6 +44,7 @@ import neatlogic.framework.restful.ratelimiter.RateLimiterTokenBucket; import neatlogic.framework.util.$; import neatlogic.framework.util.HttpRequestUtil; import neatlogic.framework.util.mongodb.IJsonSerializer; +import neatlogic.module.framework.restful.counter.ApiAccessCountService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -77,6 +77,9 @@ public class ApiDispatcher { @Resource private ApiLongCacheMapper apiLongCacheMapper; + @Resource + private ApiAccessCountService apiAccessCountService; + /* 给fastJson加载自定义序列化配置,序列化json时返回正确格式 */ @@ -158,7 +161,7 @@ public class ApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, response); Long endtime = System.currentTimeMillis(); @@ -188,7 +191,7 @@ public class ApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, new JSONReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8))); Long endtime = System.currentTimeMillis(); @@ -214,7 +217,7 @@ public class ApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, request, response); Long endtime = System.currentTimeMillis(); @@ -240,7 +243,7 @@ public class ApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 */ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj.getString("payload"), response); Long endtime = System.currentTimeMillis(); diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java index 6a34142a642d7acbda4b1ef656147577e6dc28bf..e7e31953f8f819767256a0be93890e5bb5c4baf6 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java @@ -41,13 +41,13 @@ import neatlogic.framework.restful.core.IApiComponent; import neatlogic.framework.restful.core.IBinaryStreamApiComponent; import neatlogic.framework.restful.core.IJsonStreamApiComponent; import neatlogic.framework.restful.core.publicapi.PublicApiComponentFactory; -import neatlogic.framework.restful.counter.ApiAccessCountManager; import neatlogic.framework.restful.dao.mapper.ApiLongCacheMapper; import neatlogic.framework.restful.dto.ApiHandlerVo; import neatlogic.framework.restful.dto.ApiVo; import neatlogic.framework.restful.enums.ApiType; import neatlogic.framework.restful.ratelimiter.RateLimiterTokenBucket; import neatlogic.framework.service.AuthenticationInfoService; +import neatlogic.module.framework.restful.counter.ApiAccessCountService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -79,6 +79,9 @@ public class PublicApiDispatcher { @Resource private ApiLongCacheMapper apiLongCacheMapper; + @Resource + private ApiAccessCountService apiAccessCountService; + @Resource UserMapper userMapper; @@ -175,7 +178,7 @@ public class PublicApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 **/ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, response); Long endtime = System.currentTimeMillis(); @@ -198,7 +201,7 @@ public class PublicApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 **/ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, new JSONReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8))); Long endtime = System.currentTimeMillis(); @@ -221,7 +224,7 @@ public class PublicApiDispatcher { if (restComponent != null) { if (action.equals("doservice")) { /* 统计接口访问次数 **/ - ApiAccessCountManager.putToken(token); + apiAccessCountService.putToken(token); Long starttime = System.currentTimeMillis(); Object returnV = restComponent.doService(interfaceVo, paramObj, request, response); Long endtime = System.currentTimeMillis();