src/main/java/com/xcong/excoin/configurations/MybatisPlusConfig.java
File was deleted src/main/java/com/xcong/excoin/configurations/RabbitMqConfig.java
File was deleted src/main/java/com/xcong/excoin/configurations/RedisConfig.java
File was deleted src/main/java/com/xcong/excoin/configurations/WebMvcConfig.java
@@ -1,13 +1,11 @@ package com.xcong.excoin.configurations; import com.xcong.excoin.configurations.properties.AliOssProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringBootConfiguration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; import java.util.List; /** @@ -17,10 +15,6 @@ @SpringBootConfiguration @Slf4j public class WebMvcConfig implements WebMvcConfigurer { @Resource private AliOssProperties aliOssProperties; @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { src/main/java/com/xcong/excoin/configurations/interceptor/MybatisInterceptor.java
File was deleted src/main/java/com/xcong/excoin/configurations/properties/AliOssProperties.java
File was deleted src/main/java/com/xcong/excoin/configurations/properties/ApplicationProperties.java
File was deleted src/main/java/com/xcong/excoin/configurations/properties/CustomRabbitProperties.java
File was deleted src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridWsClient.java
@@ -38,12 +38,18 @@ private static final int HEARTBEAT_TIMEOUT = 10; /** 模拟盘 WS 地址 */ private static final String WS_URL_SIM = "wss://wspap.okx.com:8443/ws/v5/private"; /** 实盘 WS 地址 */ private static final String WS_URL_PROD = "wss://ws.okx.com:8443/ws/v5/private"; /** 模拟盘公共 WS 地址 */ private static final String WS_PUBLIC_URL_SIM = "wss://wspap.okx.com:8443/ws/v5/public"; /** 实盘公共 WS 地址 */ private static final String WS_PUBLIC_URL_PROD = "wss://ws.okx.com:8443/ws/v5/public"; /** 模拟盘私有 WS 地址 */ private static final String WS_PRIVATE_URL_SIM = "wss://wspap.okx.com:8443/ws/v5/private"; /** 实盘私有 WS 地址 */ private static final String WS_PRIVATE_URL_PROD = "wss://ws.okx.com:8443/ws/v5/private"; private final ExchangeInfoEnum account; private final boolean isPublic; private final String logPrefix; private WebSocketClient webSocketClient; private ScheduledExecutorService heartbeatExecutor; private volatile ScheduledFuture<?> pongTimeoutFuture; @@ -63,8 +69,10 @@ return t; }); public OkxGridWsClient(ExchangeInfoEnum account) { public OkxGridWsClient(ExchangeInfoEnum account, boolean isPublic) { this.account = account; this.isPublic = isPublic; this.logPrefix = isPublic ? "[OKX-Grid-WS-PUB]" : "[OKX-Grid-WS-PRI]"; } public void addChannelHandler(OkxGridChannelHandler handler) { @@ -73,7 +81,7 @@ public void init() { if (!isInitialized.compareAndSet(false, true)) { log.warn("[OKX-Grid-WS] 已初始化过,跳过重复初始化"); log.warn("[{}] 已初始化过,跳过重复初始化", logPrefix); return; } connect(); @@ -81,7 +89,7 @@ } public void destroy() { log.info("[OKX-Grid-WS] 开始销毁..."); log.info("[{}] 开始销毁...", logPrefix); if (webSocketClient != null && webSocketClient.isOpen()) { for (OkxGridChannelHandler handler : channelHandlers) { handler.unsubscribe(webSocketClient); @@ -98,18 +106,23 @@ shutdownExecutorGracefully(heartbeatExecutor); if (pongTimeoutFuture != null) pongTimeoutFuture.cancel(true); shutdownExecutorGracefully(sharedExecutor); log.info("[OKX-Grid-WS] 销毁完成"); log.info("[{}] 销毁完成", logPrefix); } private void connect() { if (isConnecting.get() || !isConnecting.compareAndSet(false, true)) { log.info("[OKX-Grid-WS] 连接进行中,跳过重复请求"); log.info("[{}] 连接进行中,跳过重复请求", logPrefix); return; } try { SSLConfig.configureSSL(); System.setProperty("https.protocols", "TLSv1.2,TLSv1.3"); String wsUrl = account.isAccountType() ? WS_URL_PROD : WS_URL_SIM; String wsUrl; if (account.isAccountType()) { wsUrl = isPublic ? WS_PUBLIC_URL_PROD : WS_PRIVATE_URL_PROD; } else { wsUrl = isPublic ? WS_PUBLIC_URL_SIM : WS_PRIVATE_URL_SIM; } URI uri = new URI(wsUrl); if (webSocketClient != null) { @@ -119,12 +132,16 @@ webSocketClient = new WebSocketClient(uri) { @Override public void onOpen(ServerHandshake handshake) { log.info("[OKX-Grid-WS] 连接成功"); log.info("[{}] 连接成功", logPrefix); isConnected.set(true); isConnecting.set(false); if (sharedExecutor != null && !sharedExecutor.isShutdown()) { resetHeartbeatTimer(); if (isPublic) { subscribeAllHandlers(); } else { wsLogin(); } } } @@ -137,26 +154,26 @@ @Override public void onClose(int code, String reason, boolean remote) { log.warn("[OKX-Grid-WS] 连接关闭, code:{}, reason:{}", code, reason); log.warn("[{}] 连接关闭, code:{}, reason:{}", logPrefix, code, reason); isConnected.set(false); isConnecting.set(false); cancelPongTimeout(); if (sharedExecutor != null && !sharedExecutor.isShutdown() && !sharedExecutor.isTerminated()) { sharedExecutor.execute(() -> { try { reconnectWithBackoff(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception e) { log.error("[OKX-Grid-WS] 重连失败", e); } try { reconnectWithBackoff(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception e) { log.error("[{}] 重连失败", logPrefix, e); } }); } } @Override public void onError(Exception ex) { log.error("[OKX-Grid-WS] 发生错误", ex); log.error("[{}] 发生错误", logPrefix, ex); isConnected.set(false); } }; webSocketClient.connect(); } catch (URISyntaxException e) { log.error("[OKX-Grid-WS] URI格式错误", e); log.error("[{}] URI格式错误", logPrefix, e); isConnecting.set(false); } } @@ -180,9 +197,16 @@ args.add(loginArgs); msg.put("args", args); webSocketClient.send(msg.toJSONString()); log.info("[OKX-Grid-WS] 发送登录请求"); log.info("[{}] 发送登录请求", logPrefix); } catch (Exception e) { log.error("[OKX-Grid-WS] 登录请求构建失败", e); log.error("[{}] 登录请求构建失败", logPrefix, e); } } private void subscribeAllHandlers() { log.info("[{}] 开始订阅频道", logPrefix); for (OkxGridChannelHandler handler : channelHandlers) { handler.subscribe(webSocketClient); } } @@ -192,33 +216,27 @@ String event = response.getString("event"); String op = response.getString("op"); // 登录成功 → 订阅所有频道 if ("login".equals(event) || ("login".equals(op))) { log.info("[OKX-Grid-WS] 登录成功, 开始订阅频道"); for (OkxGridChannelHandler handler : channelHandlers) { handler.subscribe(webSocketClient); } log.info("[{}] 登录成功, 开始订阅频道", logPrefix); subscribeAllHandlers(); return; } // 订阅确认 if ("subscribe".equals(event) || "unsubscribe".equals(event)) { log.info("[OKX-Grid-WS] {}事件: {}", event, response.getString("arg")); log.info("[{}] {}事件: {}", logPrefix, event, response.getString("arg")); return; } // 错误 if ("error".equals(event)) { log.error("[OKX-Grid-WS] 错误: {}", message); log.error("[{}] 错误: {}", logPrefix, message); return; } // 数据推送 → 路由到 handler for (OkxGridChannelHandler handler : channelHandlers) { if (handler.handleMessage(response)) return; } } catch (Exception e) { log.error("[OKX-Grid-WS] 处理消息失败: {}", message, e); log.error("[{}] 处理消息失败: {}", logPrefix, message, e); } } @@ -250,9 +268,9 @@ try { if (webSocketClient != null && webSocketClient.isOpen()) { webSocketClient.send("ping"); log.debug("[OKX-Grid-WS] 发送 ping"); log.debug("[{}] 发送 ping", logPrefix); } } catch (Exception e) { log.warn("[OKX-Grid-WS] 发送 ping 失败", e); } } catch (Exception e) { log.warn("[{}] 发送 ping 失败", logPrefix, e); } } private synchronized void cancelPongTimeout() { @@ -264,9 +282,9 @@ long delayMs = 5000; while (attempt < maxAttempts) { try { Thread.sleep(delayMs); connect(); return; } catch (Exception e) { log.warn("[OKX-Grid-WS] 第{}次重连失败", attempt + 1, e); delayMs *= 2; attempt++; } catch (Exception e) { log.warn("[{}] 第{}次重连失败", logPrefix, attempt + 1, e); delayMs *= 2; attempt++; } } log.error("[OKX-Grid-WS] 超过最大重试次数({}),放弃重连", maxAttempts); log.error("[{}] 超过最大重试次数({}),放弃重连", logPrefix, maxAttempts); } private void shutdownExecutorGracefully(ExecutorService executor) { src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
@@ -44,8 +44,10 @@ @ConditionalOnProperty(prefix = "app", name = "quant", havingValue = "true") public class OkxWebSocketClientManager { /** 网格交易 WS 客户端 */ private OkxGridWsClient gridWsClient; /** 网格交易公共 WS 客户端(candle1m) */ private OkxGridWsClient gridWsClientPublic; /** 网格交易私有 WS 客户端(positions / orders-algo) */ private OkxGridWsClient gridWsClientPrivate; /** 网格交易策略服务 */ private OkxGridTradeService gridTradeService; /** 统一配置 */ @@ -102,13 +104,19 @@ gridTradeService = new OkxGridTradeService(okxConfig, okxAccount); gridTradeService.init(); // 4. 创建 WS 客户端并注册 3 个频道处理器 gridWsClient = new OkxGridWsClient(primaryAccount); gridWsClient.addChannelHandler(new OkxKlineChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClient.addChannelHandler(new OkxPositionsChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClient.addChannelHandler(new OkxAlgoOrdersChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClient.init(); log.info("[OKX-Manager] WS已连接, 已注册 3 个频道处理器: candle1m/positions/orders-algo"); // 4. 创建 WS 客户端并注册频道处理器 // 公共 WS:candle1m(K线数据) gridWsClientPublic = new OkxGridWsClient(primaryAccount, true); gridWsClientPublic.addChannelHandler(new OkxKlineChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClientPublic.init(); // 私有 WS:positions + orders-algo(持仓 + 条件单) gridWsClientPrivate = new OkxGridWsClient(primaryAccount, false); gridWsClientPrivate.addChannelHandler(new OkxPositionsChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClientPrivate.addChannelHandler(new OkxAlgoOrdersChannelHandler(okxConfig.getInstId(), gridTradeService)); gridWsClientPrivate.init(); log.info("[OKX-Manager] WS已连接, 公共: candle1m, 私有: positions/orders-algo"); // 5. 激活策略,等待首根 K 线触发基底双开 gridTradeService.startGrid(); @@ -133,11 +141,18 @@ log.error("[OKX-Manager] 停止策略失败", e); } } if (gridWsClient != null) { if (gridWsClientPublic != null) { try { gridWsClient.destroy(); gridWsClientPublic.destroy(); } catch (Exception e) { log.error("[OKX-Manager] 销毁WS客户端失败", e); log.error("[OKX-Manager] 销毁公共WS客户端失败", e); } } if (gridWsClientPrivate != null) { try { gridWsClientPrivate.destroy(); } catch (Exception e) { log.error("[OKX-Manager] 销毁私有WS客户端失败", e); } } @@ -146,8 +161,9 @@ /** @return 网格交易策略服务实例 */ public OkxGridTradeService getGridTradeService() { return gridTradeService; } /** @return 网格交易 WS 客户端实例 */ public OkxGridWsClient getGridWsClient() { return gridWsClient; } /** @return 统一配置实例 */ /** @return 网格交易公共 WS 客户端实例 */ public OkxGridWsClient getGridWsClientPublic() { return gridWsClientPublic; } /** @return 网格交易私有 WS 客户端实例 */ public OkxGridWsClient getGridWsClientPrivate() { return gridWsClientPrivate; } public OkxConfig getOkxConfig() { return okxConfig; } } src/main/java/com/xcong/excoin/modules/okxNewPrice/okxpi/config/ResponseHandler.java
@@ -21,7 +21,7 @@ } public static String handleResponse(Request request, boolean showLimitUsage) { try (Response response = OkHttpUtils.okHttpClient.newCall(request).execute()) {//OkHttpUtils.builder().okHttpClient try (Response response = OkHttpUtils.getClient().newCall(request).execute()) { String responseAsString = getResponseBodyAsString(response.body()); if (response.code() >= HTTP_STATUS_CODE_400 && response.code() <= HTTP_STATUS_CODE_499) { src/main/java/com/xcong/excoin/modules/okxNewPrice/okxpi/config/utils/OkHttpUtils.java
@@ -74,6 +74,16 @@ } /** * 确保 OkHttpClient 在任何请求路径下都已初始化(包括直接使用 new Request.Builder() 的场景)。 */ public static OkHttpClient getClient() { if (okHttpClient == null) { new OkHttpUtils(); // 触发构造函数中的 DCL 初始化 } return okHttpClient; } /** * 创建OkHttpUtils * * @return src/main/java/com/xcong/excoin/modules/okxNewPrice/okx文档.txt
New file Diff too large src/main/resources/application-okx.yml
New file @@ -0,0 +1,2 @@ mybatis-plus: mapper-locations: classpath*:mapper/blackchain/*.xml, classpath*:mapper/ding/*.xml, classpath*:mapper/price/*.xml, classpath*:mapper/combom/*.xml, classpath*:mapper/record/*.xml, classpath*:mapper/uinfo/*.xml, classpath*:mapper/push/*.xml, classpath*:mapper/coin/*.xml, classpath*:mapper/user/*.xml, classpath*:mapper/demo/*.xml src/main/resources/application-test.yml
@@ -45,47 +45,6 @@ ## 国际化配置 messages: basename: i18n/messages ## redis配置 redis: # Redis数据库索引(默认为 0) database: 8 # Redis服务器地址 host: 120.27.238.55 # Redis服务器连接端口 port: 6479 # Redis 密码 password: d3y6dsdl;f.327 lettuce: pool: # 连接池中的最小空闲连接 min-idle: 8 # 连接池中的最大空闲连接 max-idle: 500 # 连接池最大连接数(使用负值表示没有限制) max-active: 2000 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: 10000 # 连接超时时间(毫秒) timeout: 500000 rabbitmq: host: 120.27.238.55 port: 5672 username: ct_rabbit password: 123456 publisher-confirm-type: correlated #custom: # rabbitmq: # host: 120.27.238.55 # port: 5672 # username: ct_rabbit # password: 123456 mybatis-plus: mapper-locations: classpath:mapper/**/*.xml app: debug: false src/main/resources/application.yml
@@ -47,47 +47,6 @@ ## 国际化配置 messages: basename: i18n/messages ## redis配置 redis: # Redis数据库索引(默认为 0) database: 13 # Redis服务器地址 host: 120.27.238.55 # Redis服务器连接端口 port: 6479 # Redis 密码 password: d3y6dsdl;f.327 lettuce: pool: # 连接池中的最小空闲连接 min-idle: 8 # 连接池中的最大空闲连接 max-idle: 500 # 连接池最大连接数(使用负值表示没有限制) max-active: 2000 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: 10000 # 连接超时时间(毫秒) timeout: 500000 rabbitmq: host: 120.27.238.55 port: 5672 username: ct_rabbit password: 123456 publisher-confirm-type: correlated #custom: # rabbitmq: # host: 120.27.238.55 # port: 5672 # username: ct_rabbit # password: 123456 mybatis-plus: mapper-locations: classpath:mapper/**/*.xml app: debug: false src/main/resources/mapper/TestUserDao.xml
File was deleted src/main/resources/mapper/contract/ContractEntrustOrderDao.xml
File was deleted src/main/resources/mapper/contract/ContractHoldOrderDao.xml
File was deleted src/main/resources/mapper/contract/ContractOrderDao.xml
File was deleted src/main/resources/mapper/home/MemberQuickBuySaleDao.xml
File was deleted src/main/resources/mapper/member/AgentReturnDao.xml
File was deleted src/main/resources/mapper/member/AppVersionDao.xml
File was deleted src/main/resources/mapper/member/MemberAccountFlowEntityDao.xml
File was deleted src/main/resources/mapper/member/MemberAccountMoneyChangeDao.xml
File was deleted src/main/resources/mapper/member/MemberAuthenticationDao.xml
File was deleted src/main/resources/mapper/member/MemberCoinAddressDao.xml
File was deleted src/main/resources/mapper/member/MemberCoinChargeDao.xml
File was deleted src/main/resources/mapper/member/MemberDao.xml
File was deleted src/main/resources/mapper/member/MemberLevelRateDao.xml
File was deleted src/main/resources/mapper/member/MemberPaymentMethodDao.xml
File was deleted src/main/resources/mapper/member/MemberSelectSymbolsDao.xml
File was deleted src/main/resources/mapper/member/MemberSettingDao.xml
File was deleted src/main/resources/mapper/member/MemberWalletAgentDao.xml
File was deleted src/main/resources/mapper/member/MemberWalletCoinDao.xml
File was deleted src/main/resources/mapper/member/MemberWalletContractDao.xml
File was deleted src/main/resources/mapper/member/MemberWalletContractSimulateDao.xml
File was deleted src/main/resources/mapper/platform/PlatformCnyUsdtExchangeDao.xml
File was deleted src/main/resources/mapper/platform/PlatformFeeSettingDao.xml
File was deleted src/main/resources/mapper/platform/PlatformSymbolsCoinDao.xml
File was deleted src/main/resources/mapper/platform/PlatformSymbolsContractDao.xml
File was deleted src/main/resources/mapper/platform/PlatformSymbolsSkuDao.xml
File was deleted src/main/resources/mapper/platform/TradeSettingDao.xml
File was deleted src/main/resources/mapper/walletCoinOrder/OrderCoinDealDao.xml
File was deleted src/main/resources/mapper/walletCoinOrder/OrderCoinsDao.xml
File was deleted