From 64f826e5bebf7fb5abeade86d1c8760a55ac9a15 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Mon, 22 Jul 2024 09:54:07 +0800
Subject: [PATCH] 1
---
mexcClient-废弃/src/main/java/org/example/wsClient/GateClient.java | 208 ++++
bitgetsClient/src/main/resources/application.yml | 75 +
geteClient/src/main/resources/static/index.html | 6
mexcClient-废弃/src/main/java/org/example/server/impl/CurrencySerivceImpl.java | 15
kucoinClient/.gitignore | 33
mexcClient/src/main/resources/static/index.html | 6
kucoinClient/src/main/resources/static/index.html | 6
geteClient/.gitignore | 33
mexcClient/.gitignore | 33
kucoinClient/src/main/resources/application.yml | 75 +
geteClient/pom.xml | 152 +++
mexcClient-废弃/src/main/java/org/example/wsClient/MexcClient.java | 176 ++++
bitgetsClient/.gitignore | 33
mexcClient-废弃/src/main/resources/application.yml | 75 +
mexcClient/src/main/java/org/example/mexcclient/MexcClientApplication.java | 13
mexcClient-废弃/src/main/java/org/example/util/RedisUtil.java | 121 ++
mexcClient-废弃/src/main/java/org/example/WsClientApplication.java | 19
mexcClient-废弃/pom.xml | 142 +++
mexcClient/src/main/resources/application.yml | 75 +
bitgetsClient/src/main/resources/static/index.html | 6
geteClient/src/main/resources/application.yml | 75 +
mexcClient-废弃/src/main/java/org/example/server/CurrencySerivce.java | 9
bitgetsClient/src/main/java/org/example/bitgetsclient/BitgetsClientApplication.java | 13
geteClient/src/main/java/org/example/geteclient/GeteClientApplication.java | 13
mexcClient-废弃/src/main/java/org/example/WsBean/MexcWsBean.java | 173 +++
bitgetsClient/pom.xml | 152 +++
kucoinClient/src/main/java/org/example/kucoinclient/KucoinClientApplication.java | 13
kucoinClient/pom.xml | 162 +++
mexcClient-废弃/src/main/java/org/example/pojo/Currency.java | 25
mexcClient-废弃/src/main/java/org/example/wsClient/KucoinClient.java | 254 +++++
mexcClient-废弃/src/main/java/org/example/wsClient/BitgetClient.java | 218 ++++
mexcClient-废弃/src/main/java/org/example/ThreadConfig/AsyncConfiguration.java | 35
mexcClient/pom.xml | 152 +++
mexcClient-废弃/src/main/java/org/example/dao/CurrencyMapper.java | 14
34 files changed, 2,610 insertions(+), 0 deletions(-)
diff --git a/bitgetsClient/.gitignore b/bitgetsClient/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/bitgetsClient/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/bitgetsClient/pom.xml b/bitgetsClient/pom.xml
new file mode 100644
index 0000000..58a1a48
--- /dev/null
+++ b/bitgetsClient/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.example</groupId>
+ <artifactId>bitgetsClient</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>bitgetsClient</name>
+ <description>bitgetsClient</description>
+ <properties>
+ <java.version>1.8</java.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <spring-boot.version>2.6.13</spring-boot.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version> <!-- 根据需要选择最新的版本 -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>20.0</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>3.4.3.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <dependency>
+ <groupId>io.socket</groupId>
+ <artifactId>engine.io-client</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mybatis.spring.boot</groupId>
+ <artifactId>mybatis-spring-boot-starter</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ <configuration>
+ <mainClass>org.example.bitgetsclient.BitgetsClientApplication</mainClass>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>repackage</id>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/bitgetsClient/src/main/java/org/example/bitgetsclient/BitgetsClientApplication.java b/bitgetsClient/src/main/java/org/example/bitgetsclient/BitgetsClientApplication.java
new file mode 100644
index 0000000..edb9428
--- /dev/null
+++ b/bitgetsClient/src/main/java/org/example/bitgetsclient/BitgetsClientApplication.java
@@ -0,0 +1,13 @@
+package org.example.bitgetsclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BitgetsClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BitgetsClientApplication.class, args);
+ }
+
+}
diff --git a/bitgetsClient/src/main/resources/application.yml b/bitgetsClient/src/main/resources/application.yml
new file mode 100644
index 0000000..1db8b3c
--- /dev/null
+++ b/bitgetsClient/src/main/resources/application.yml
@@ -0,0 +1,75 @@
+server:
+ port: 8081
+
+
+spring:
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 1
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 99
+ # 连接池的最大数据库连接数
+ max-active: 99
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+
+ druid:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: Greysparrow
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: false
diff --git a/bitgetsClient/src/main/resources/static/index.html b/bitgetsClient/src/main/resources/static/index.html
new file mode 100644
index 0000000..89bb8ba
--- /dev/null
+++ b/bitgetsClient/src/main/resources/static/index.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<h1>hello word!!!</h1>
+<p>this is a html page</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/geteClient/.gitignore b/geteClient/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/geteClient/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/geteClient/pom.xml b/geteClient/pom.xml
new file mode 100644
index 0000000..ab311de
--- /dev/null
+++ b/geteClient/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.example</groupId>
+ <artifactId>geteClient</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>geteClient</name>
+ <description>geteClient</description>
+ <properties>
+ <java.version>1.8</java.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <spring-boot.version>2.6.13</spring-boot.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version> <!-- 根据需要选择最新的版本 -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>20.0</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>3.4.3.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <dependency>
+ <groupId>io.socket</groupId>
+ <artifactId>engine.io-client</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mybatis.spring.boot</groupId>
+ <artifactId>mybatis-spring-boot-starter</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ <configuration>
+ <mainClass>org.example.geteclient.GeteClientApplication</mainClass>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>repackage</id>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/geteClient/src/main/java/org/example/geteclient/GeteClientApplication.java b/geteClient/src/main/java/org/example/geteclient/GeteClientApplication.java
new file mode 100644
index 0000000..e055916
--- /dev/null
+++ b/geteClient/src/main/java/org/example/geteclient/GeteClientApplication.java
@@ -0,0 +1,13 @@
+package org.example.geteclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class GeteClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(GeteClientApplication.class, args);
+ }
+
+}
diff --git a/geteClient/src/main/resources/application.yml b/geteClient/src/main/resources/application.yml
new file mode 100644
index 0000000..3c842cc
--- /dev/null
+++ b/geteClient/src/main/resources/application.yml
@@ -0,0 +1,75 @@
+server:
+ port: 8082
+
+
+spring:
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 1
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 99
+ # 连接池的最大数据库连接数
+ max-active: 99
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+
+ druid:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: Greysparrow
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: false
diff --git a/geteClient/src/main/resources/static/index.html b/geteClient/src/main/resources/static/index.html
new file mode 100644
index 0000000..89bb8ba
--- /dev/null
+++ b/geteClient/src/main/resources/static/index.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<h1>hello word!!!</h1>
+<p>this is a html page</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/kucoinClient/.gitignore b/kucoinClient/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/kucoinClient/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/kucoinClient/pom.xml b/kucoinClient/pom.xml
new file mode 100644
index 0000000..3db7ded
--- /dev/null
+++ b/kucoinClient/pom.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.example</groupId>
+ <artifactId>kucoinClient</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>kucoinClient</name>
+ <description>kucoinClient</description>
+ <properties>
+ <java.version>1.8</java.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <spring-boot.version>2.6.13</spring-boot.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version> <!-- 根据需要选择最新的版本 -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>20.0</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>3.4.3.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <dependency>
+ <groupId>io.socket</groupId>
+ <artifactId>engine.io-client</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mybatis.spring.boot</groupId>
+ <artifactId>mybatis-spring-boot-starter</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ <configuration>
+ <mainClass>org.example.kucoinclient.KucoinClientApplication</mainClass>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>repackage</id>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/kucoinClient/src/main/java/org/example/kucoinclient/KucoinClientApplication.java b/kucoinClient/src/main/java/org/example/kucoinclient/KucoinClientApplication.java
new file mode 100644
index 0000000..6485959
--- /dev/null
+++ b/kucoinClient/src/main/java/org/example/kucoinclient/KucoinClientApplication.java
@@ -0,0 +1,13 @@
+package org.example.kucoinclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class KucoinClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(KucoinClientApplication.class, args);
+ }
+
+}
diff --git a/kucoinClient/src/main/resources/application.yml b/kucoinClient/src/main/resources/application.yml
new file mode 100644
index 0000000..ad19825
--- /dev/null
+++ b/kucoinClient/src/main/resources/application.yml
@@ -0,0 +1,75 @@
+server:
+ port: 8083
+
+
+spring:
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 1
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 99
+ # 连接池的最大数据库连接数
+ max-active: 99
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+
+ druid:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: Greysparrow
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: false
diff --git a/kucoinClient/src/main/resources/static/index.html b/kucoinClient/src/main/resources/static/index.html
new file mode 100644
index 0000000..89bb8ba
--- /dev/null
+++ b/kucoinClient/src/main/resources/static/index.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<h1>hello word!!!</h1>
+<p>this is a html page</p>
+</body>
+</html>
\ No newline at end of file
diff --git "a/mexcClient-\345\272\237\345\274\203/pom.xml" "b/mexcClient-\345\272\237\345\274\203/pom.xml"
new file mode 100644
index 0000000..ddbd9f1
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/pom.xml"
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.example</groupId>
+ <artifactId>mexcClient</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>mexcClient</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version> <!-- 根据需要选择最新的版本 -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>20.0</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>3.4.3.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <dependency>
+ <groupId>io.socket</groupId>
+ <artifactId>engine.io-client</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mybatis.spring.boot</groupId>
+ <artifactId>mybatis-spring-boot-starter</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ </dependencies>
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <build>
+ <finalName>mexcClient</finalName>
+ <plugins>
+ <!-- 打包项目 mvn clean package -->
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <!-- 指定main方法入口 -->
+ <configuration>
+ <mainClass>org.example.WsClientApplication</mainClass>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/ThreadConfig/AsyncConfiguration.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/ThreadConfig/AsyncConfiguration.java"
new file mode 100644
index 0000000..1f7882e
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/ThreadConfig/AsyncConfiguration.java"
@@ -0,0 +1,35 @@
+package org.example.ThreadConfig;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @program: dabaogp
+ * @description: 线程池配置
+ * @create: 2024-06-25 16:37
+ **/
+@Configuration
+public class AsyncConfiguration {
+
+ @Bean(name = "threadPoolTaskExecutor")
+ public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+
+ executor.setCorePoolSize(200); // 核心线程数, 根据需求进行调整
+ executor.setMaxPoolSize(400); // 最大线程数, 适当设置以避免资源耗尽
+ executor.setQueueCapacity(500); // 队列容量, 适当限制以避免请求堆积
+ executor.setKeepAliveSeconds(30); // 线程空闲时的存活时间为30秒,减少系统开销
+ executor.setThreadNamePrefix("Thread-"); // 线程名称的前缀
+
+ // 使用 CallerRunsPolicy 拒绝策略,以减少任务被拒绝时带来的负担
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // 初始化线程池,配置其他参数(不过可以根据需要添加)
+ executor.initialize(); // 明确初始化,提升代码可读性
+
+ return executor; // 返回配置好的线程池
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsBean/MexcWsBean.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsBean/MexcWsBean.java"
new file mode 100644
index 0000000..e2a6a4d
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsBean/MexcWsBean.java"
@@ -0,0 +1,173 @@
+package org.example.WsBean;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.example.pojo.Currency;
+import org.example.server.impl.CurrencySerivceImpl;
+import org.example.wsClient.BitgetClient;
+import org.example.wsClient.GateClient;
+import org.example.wsClient.KucoinClient;
+import org.example.wsClient.MexcClient;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassDescription: 客户端请求类
+ * @JdkVersion: 1.8
+ * @Created: 2023/8/31 16:13
+ */
+@Slf4j
+@Configuration
+public class MexcWsBean {
+
+ @Autowired
+ private CurrencySerivceImpl currencyService;
+
+ @Autowired
+ @Qualifier("threadPoolTaskExecutor")
+ private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+
+ @Bean
+ public void mexcWebsocketRunClientMap() {
+ List<Currency> mexc = currencyService.list(new LambdaQueryWrapper<Currency>().eq(Currency::getSource, "mexc"));
+ if (!CollectionUtils.isEmpty(mexc)) {
+ int batchSize = 30; // 每个线程处理的数据量
+ int totalSize = mexc.size();
+ int threadCount = (int) Math.ceil((double) totalSize / batchSize); // 计算需要的线程数
+
+ for (int i = 0; i < threadCount; i++) {
+ int fromIndex = i * batchSize;
+ int toIndex = Math.min(fromIndex + batchSize, totalSize);
+ List<Currency> sublist = mexc.subList(fromIndex, toIndex);
+
+ // 使用自定义线程池提交任务
+ threadPoolTaskExecutor.execute(new MexcClient(sublist)::start);
+ }
+
+ }
+ }
+
+// @Bean
+// public void gateWebsocketRunClientMap() {
+// List<Currency> mexc = currencyService.list(new LambdaQueryWrapper<Currency>().eq(Currency::getSource, "gate"));
+// if (!CollectionUtils.isEmpty(mexc)) {
+// int batchSize = 100; // 每个线程处理的数据量
+// int totalSize = mexc.size();
+// int threadCount = (int) Math.ceil((double) totalSize / batchSize); // 计算需要的线程数
+//
+// for (int i = 0; i < threadCount; i++) {
+// int fromIndex = i * batchSize;
+// int toIndex = Math.min(fromIndex + batchSize, totalSize);
+// List<Currency> sublist = mexc.subList(fromIndex, toIndex);
+//
+// // 使用自定义线程池提交任务
+// threadPoolTaskExecutor.execute(new GateClient(sublist)::start);
+// }
+//
+// }
+// }
+//
+// @Bean
+// public void bitgetWebsocketRunClientMap() throws JSONException, JsonProcessingException {
+// List<Currency> mexc = currencyService.list(new LambdaQueryWrapper<Currency>().eq(Currency::getSource, "bitget"));
+// if (!CollectionUtils.isEmpty(mexc)) {
+// int batchSize = 100; // 每个线程处理的数据量
+// int totalSize = mexc.size();
+// int threadCount = (int) Math.ceil((double) totalSize / batchSize); // 计算需要的线程数
+//
+// // 使用循环创建多个线程并提交任务
+// for (int i = 0; i < threadCount; i++) {
+// int fromIndex = i * batchSize; // 计算起始索引
+// int toIndex = Math.min(fromIndex + batchSize, totalSize); // 计算结束索引
+// List<Currency> sublist = mexc.subList(fromIndex, toIndex); // 切分子列表
+// String parameter = getParameter(sublist); // 获取参数
+// // 使用自定义线程池提交任务
+// threadPoolTaskExecutor.execute(new BitgetClient(parameter)::start); // 提交到线程池执行
+// }
+// }
+// }
+//
+// @Bean
+// public void kucoinWebsocketRunClientMap() throws Exception {
+// List<Currency> mexc = currencyService.list(new LambdaQueryWrapper<Currency>().eq(Currency::getSource, "kucoin"));
+// if (!CollectionUtils.isEmpty(mexc)) {
+// String result = doPost();
+// JSONObject jsonObject = new JSONObject(result);
+// String token = jsonObject.getJSONObject("data").getString("token");
+// int batchSize = 100; // 每个线程处理的数据量
+// int totalSize = mexc.size();
+// int threadCount = (int) Math.ceil((double) totalSize / batchSize); // 计算需要的线程数
+//
+// for (int i = 0; i < threadCount; i++) {
+// int fromIndex = i * batchSize;
+// int toIndex = Math.min(fromIndex + batchSize, totalSize);
+// List<Currency> sublist = mexc.subList(fromIndex, toIndex);
+//
+// // 使用自定义线程池提交任务
+// threadPoolTaskExecutor.execute(new KucoinClient(sublist,token)::start);
+// }
+//
+// }
+// }
+
+ public static String doPost() throws Exception {
+ String url = "https://api.kucoin.com/api/v1/bullet-public";
+ HttpPost httpPost = new HttpPost(url);
+ DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
+ List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+ httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+ HttpResponse response = defaultHttpClient.execute(httpPost);
+ HttpEntity respEntity = response.getEntity();
+ String text = EntityUtils.toString(respEntity, "UTF-8");
+ defaultHttpClient.getConnectionManager().shutdown();
+ return text;
+ }
+
+ public String getParameter(List<Currency> list) throws JsonProcessingException, JSONException {
+ // 创建一个ObjectMapper实例
+ ObjectMapper mapper = new ObjectMapper();
+ List<String> symbolList = list.stream().map(Currency::getSymbol).collect(Collectors.toList());
+ // 使用Map构建JSON对象
+ Map<String, Object> jsonMap = new HashMap<>();
+ jsonMap.put("op", "subscribe");
+ List<Map<String, String>> mapList = new ArrayList<>();
+ symbolList.forEach(f->{
+ Map<String, String> argsMap = new HashMap<>();
+ argsMap.put("instType", "SPOT");
+ argsMap.put("channel", "books15");
+ argsMap.put("instId", f);
+ mapList.add(argsMap);
+ });
+ jsonMap.put("args", mapList);
+
+ // 将Map转换为JSON字符串
+ String jsonString = mapper.writeValueAsString(jsonMap);
+ return jsonString;
+
+ }
+}
+
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsClientApplication.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsClientApplication.java"
new file mode 100644
index 0000000..54aa288
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/WsClientApplication.java"
@@ -0,0 +1,19 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @ClassDescription:
+ * @JdkVersion: 1.8
+ * @Created: 2023/8/31 16:09
+ */
+@EnableScheduling
+@SpringBootApplication
+public class WsClientApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(WsClientApplication.class, args);
+ }
+}
+
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/dao/CurrencyMapper.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/dao/CurrencyMapper.java"
new file mode 100644
index 0000000..86b645b
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/dao/CurrencyMapper.java"
@@ -0,0 +1,14 @@
+package org.example.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.example.pojo.Currency;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-15 17:45
+ **/
+@Mapper
+public interface CurrencyMapper extends BaseMapper<Currency> {
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/pojo/Currency.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/pojo/Currency.java"
new file mode 100644
index 0000000..2e0e322
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/pojo/Currency.java"
@@ -0,0 +1,25 @@
+package org.example.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+/**
+ * @program: demo
+ * @description: 交易对
+ * @create: 2024-07-15 17:41
+ **/
+@Data
+public class Currency {
+ @TableId(value = "id",type = IdType.AUTO)
+ private String id;
+ //交易对
+ private String symbol;
+ //交易币
+ private String baseAsset;
+ //计价币
+ private String quoteAsset;
+ //来源
+ private String source;
+
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/CurrencySerivce.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/CurrencySerivce.java"
new file mode 100644
index 0000000..d50a81f
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/CurrencySerivce.java"
@@ -0,0 +1,9 @@
+package org.example.server;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-16 15:23
+ **/
+public interface CurrencySerivce {
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/impl/CurrencySerivceImpl.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/impl/CurrencySerivceImpl.java"
new file mode 100644
index 0000000..1b220f2
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/server/impl/CurrencySerivceImpl.java"
@@ -0,0 +1,15 @@
+package org.example.server.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.example.dao.CurrencyMapper;
+import org.example.pojo.Currency;
+import org.springframework.stereotype.Service;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-16 15:23
+ **/
+@Service
+public class CurrencySerivceImpl extends ServiceImpl<CurrencyMapper, Currency> {
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/util/RedisUtil.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/util/RedisUtil.java"
new file mode 100644
index 0000000..dab4e20
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/util/RedisUtil.java"
@@ -0,0 +1,121 @@
+package org.example.util;
+
+import redis.clients.jedis.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class RedisUtil {
+ private static JedisPool jedisPool;
+
+ static {
+ jedisPool = new JedisPool(new JedisPoolConfig(), "localhost", 6379);
+ }
+
+ // 私有构造方法,防止实例化
+ private RedisUtil() {}
+
+ public static void set(String key, String value) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.set(key, value);
+ }
+ }
+
+ public static String get(String key) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ return jedis.get(key);
+ }
+ }
+
+ public static void hset(String key, String field, String value) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.hset(key, field, value);
+ }
+ }
+
+ public static String hget(String key, String field) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ return jedis.hget(key, field);
+ }
+ }
+
+ public static void lpush(String key, String... values) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.lpush(key, values);
+ }
+ }
+
+ public static List<String> lrange(String key, long start, long end) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ return jedis.lrange(key, start, end);
+ }
+ }
+
+ public static void sadd(String key, String... members) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.sadd(key, members);
+ }
+ }
+
+ public static Set<String> smembers(String key) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ return jedis.smembers(key);
+ }
+ }
+
+ public static void zadd(String key, double score, String member) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.zadd(key, score, member);
+ }
+ }
+
+ public static Set<String> zrange(String key, long start, long end) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ return jedis.zrange(key, start, end);
+ }
+ }
+
+ public static void delete(String key) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.del(key);
+ }
+ }
+
+ public static void disconnect() {
+ jedisPool.close();
+ }
+
+ // 示例用法
+ public static void main(String[] args) {
+ // 直接使用 RedisUtil 的静态方法
+ RedisUtil.set("mykey", "myvalue");
+ String value = RedisUtil.get("mykey");
+ System.out.println("Value for 'mykey': " + value);
+
+ RedisUtil.hset("user:1", "name", "Alice");
+ String userName = RedisUtil.hget("user:1", "name");
+ System.out.println("Name for 'user:1': " + userName);
+
+ RedisUtil.lpush("mylist", "element1", "element2", "element3");
+ List<String> listValues = RedisUtil.lrange("mylist", 0, -1);
+ System.out.println("Values in 'mylist': " + listValues);
+
+ RedisUtil.sadd("myset", "member1", "member2", "member3");
+ Set<String> setMembers = RedisUtil.smembers("myset");
+ System.out.println("Members in 'myset': " + setMembers);
+
+ RedisUtil.zadd("myzset", 1.0, "member1");
+ RedisUtil.zadd("myzset", 2.0, "member2");
+ Set<String> zsetMembers = RedisUtil.zrange("myzset", 0, -1);
+ System.out.println("Members in 'myzset': " + zsetMembers);
+
+ RedisUtil.delete("mykey");
+ RedisUtil.delete("user:1");
+ RedisUtil.delete("mylist");
+ RedisUtil.delete("myset");
+ RedisUtil.delete("myzset");
+
+ RedisUtil.disconnect();
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/BitgetClient.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/BitgetClient.java"
new file mode 100644
index 0000000..9bc4f64
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/BitgetClient.java"
@@ -0,0 +1,218 @@
+package org.example.wsClient;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import lombok.extern.slf4j.Slf4j;
+import org.example.pojo.Currency;
+import org.example.util.RedisUtil;
+import org.json.JSONException;
+import org.springframework.context.annotation.Bean;
+import org.springframework.util.CollectionUtils;
+
+import javax.websocket.*;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@ClientEndpoint
+@Slf4j
+public class BitgetClient {
+
+ private static final String WS_ENDPOINT = "wss://ws.bitget.com/v2/ws/public"; // WebSocket 接口地址
+ private static final long PING_INTERVAL = 20000; // 心跳间隔,单位毫秒
+ private static final String PING_MESSAGE = "ping"; // 心跳消息
+ private static final int MAX_RECONNECT_ATTEMPTS = 5; // 最大重连次数
+ private final String subscriptions; // 订阅内容
+ private final ScheduledExecutorService executorService; // 定义调度任务执行服务
+ private Session session; // WebSocket 会话
+
+ private final Object lock = new Object(); // 使用锁对象以确保线程安全
+ private boolean reconnecting = false; // 重连状态
+ private int reconnectAttempts = 0; // 当前重连次数
+
+ // 静态单例 ObjectMapper 实例,避免重复创建
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final Gson gson = new Gson(); // 静态 Gson 实例
+
+ // 构造方法,初始化订阅内容和调度服务
+ public BitgetClient(String subscriptions) {
+ this.subscriptions = subscriptions; // 初始化订阅内容
+ this.executorService = Executors.newScheduledThreadPool(1); // 初始化调度线程池
+ }
+
+
+
+ public void start() {
+ try {
+ connect(); // 尝试连接
+ if (session == null) {
+ log.info("无法在超时内连接到服务器。"); // 记录连接失败的信息
+ return; // 如果连接失败,直接返回
+ }
+
+ // 定期发送心跳
+ executorService.scheduleAtFixedRate(this::sendPing, PING_INTERVAL, PING_INTERVAL, TimeUnit.MILLISECONDS);
+ // 发送订阅消息
+ session.getBasicRemote().sendText(subscriptions); // 发送订阅信息
+
+ synchronized (this) {
+ this.wait(); // 等待 WebSocket 消息到来
+ }
+
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // 恢复中断状态
+ log.error("线程被中断: " + e.getMessage(), e); // 记录线程中断的错误
+ } catch (Exception e) {
+ log.error("bitget ws 连接过程中发生异常: " + e.getMessage(), e); // 记录连接过程中发生的异常
+ } finally {
+ executorService.shutdownNow(); // 尝试立即关闭调度服务
+ }
+ }
+
+ private void connect() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+ container.connectToServer(this, new URI(WS_ENDPOINT)); // 连接 WebSocket 服务
+ }
+
+ @OnOpen
+ public void onOpen(Session session) {
+ log.info("bitget ws 已连接到服务器。"); // 记录连接成功的信息
+ this.session = session; // 存储会话
+ synchronized (this) {
+ this.notify(); // 通知等待的线程
+ }
+ reconnectAttempts = 0; // 连接成功重置重连次数
+ }
+
+ @OnMessage
+ public void onMessage(String message) {
+ try {
+ // 将消息解析为 Map
+ Map<String, Object> map = parseMessage(message); // 调用共用方法解析
+ if (map != null && map.containsKey("arg") && map.containsKey("data")) { // 确保 map 不为 null 且包含必要的键
+ JsonNode dataNode = getDataNode(message); // 获取数据节点
+
+ // 确保 dataNode 不为 null,以避免空指针异常
+ if (dataNode != null) {
+ // 存储数据到 HashMap
+ Map<String, Object> bidAskMap = new HashMap<>(); // 变量命名更具描述性
+ bidAskMap.put("bids", dataNode.get("bids")); // 获取并存储 bids
+ bidAskMap.put("asks", dataNode.get("asks")); // 获取并存储 asks
+
+ Map<String, Object> argMap = gson.fromJson(map.get("arg").toString(), new TypeToken<Map<String, Object>>() {}.getType()); // 解析 arg 为 Map
+ String key = "bitget" + argMap.get("instId"); // 构建 Redis 存储的键
+
+ // 存储到 Redis,使用 ObjectMapper 转换为 JSON 字符串
+ String jsonData = objectMapper.writeValueAsString(bidAskMap); // 先将 HashMap 转换为 JSON 字符串
+ RedisUtil.set(key, jsonData); // 存储数据
+ }
+ }
+ } catch (JsonSyntaxException e) {
+ log.error("JSON 解析错误: " + e.getMessage(), e); // 记录 JSON 解析错误
+ } catch (IOException e) {
+ log.error("对象转换时发生 I/O 异常: " + e.getMessage(), e); // 记录对象转换 I/O 异常
+ } catch (Exception e) {
+ log.error("处理消息时发生异常: " + e.getMessage(), e); // 记录处理消息时发生的异常
+ }
+ }
+
+
+ // 解析消息的共用方法
+ private Map<String, Object> parseMessage(String message) {
+ if(!message.equals("pong")){
+ return gson.fromJson(message, new TypeToken<Map<String, Object>>() {}.getType()); // 将消息解析为 Map
+ }
+ return null;
+ }
+
+ // 获取数据节点的共用方法
+ private JsonNode getDataNode(String message) throws JsonProcessingException {
+ JsonNode jsonNode = objectMapper.readTree(message); // 使用静态 ObjectMapper,避免重复创建
+ return jsonNode.get("data").get(0); // 获取第一个数据节点
+ }
+
+ @OnClose
+ public void onClose() {
+ log.info("bitget ws 连接已关闭,尝试重新连接..."); // 记录连接关闭的信息
+ handleConnectionClosedOrError(); // 处理连接关闭事件
+ }
+
+ @OnError
+ public void onError(Throwable throwable) {
+ log.error("bitget ws 发生错误: " + throwable.getMessage(), throwable); // 记录错误信息
+ handleConnectionClosedOrError(); // 处理错误事件
+ }
+
+ private void handleConnectionClosedOrError() {
+ synchronized (lock) {
+ if (!reconnecting) {
+ reconnecting = true; // 开始重连
+ executorService.execute(this::attemptReconnect); // 执行重连操作
+ }
+ }
+ }
+
+ private void attemptReconnect() {
+ if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) { // 检查重连次数是否超过限制
+ try {
+ log.info("bitget ws 开始重连"); // 记录开始重连的信息
+ connect(); // 尝试重连
+ log.info("bitget ws 重连成功"); // 成功重连的日志
+ reconnectAttempts = 0; // 重连成功,重置重连次数
+ } catch (Exception e) {
+ reconnectAttempts++; // 增加重连尝试次数
+ log.warn("bitget ws 重连失败,尝试次数: " + reconnectAttempts, e); // 记录重连失败的警告信息
+ // 采用指数退避策略,增加重连间隔
+ long waitTime = Math.min(60, (long) Math.pow(2, reconnectAttempts)) * 1000; // 最大等待时间为 60 秒
+ scheduleReconnect(waitTime); // 调度下次重连
+ }
+ } else {
+ log.error("超过最大重连次数,停止重连"); // 超过最大重连次数
+ reconnecting = false; // 重连状态重置
+ }
+ }
+
+ private void scheduleReconnect(long waitTime) { // 接受等待时间参数
+ if (!executorService.isShutdown()) {
+ executorService.schedule(this::attemptReconnect, waitTime, TimeUnit.MILLISECONDS); // 调度重连
+ }
+ }
+
+ private void sendPing() {
+ try {
+ if (session != null) {
+ session.getBasicRemote().sendText(PING_MESSAGE); // 发送心跳消息
+ }
+ } catch (Exception e) {
+ log.error("发送心跳失败", e); // 记录发送心跳失败的错误
+ }
+ }
+
+ public String getParameter(String symbol) throws JsonProcessingException {
+ // 使用 ObjectMapper 构建 JSON 请求
+ Map<String, Object> jsonMap = new HashMap<>();
+ jsonMap.put("op", "subscribe"); // 设置操作类型
+ Map<String, Object> argsMap = new HashMap<>();
+ jsonMap.put("args", argsMap); // 参数放入请求
+
+ // 设置请求参数
+ argsMap.put("instType", "SPOT"); // 交易类型
+ argsMap.put("channel", "books15"); // 渠道类型
+ argsMap.put("instId", symbol); // 交易对符号
+
+ // 返回 JSON 字符串
+ return objectMapper.writeValueAsString(jsonMap); // 使用单一的 ObjectMapper 实例
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/GateClient.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/GateClient.java"
new file mode 100644
index 0000000..f4a6224
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/GateClient.java"
@@ -0,0 +1,208 @@
+package org.example.wsClient;
+
+import com.alibaba.druid.support.json.JSONUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import lombok.extern.slf4j.Slf4j;
+import org.example.pojo.Currency;
+import org.example.util.RedisUtil;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import javax.websocket.*;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @program: demo
+ * @description: GateClient 用于与 Gate.io WebSocket API 进行交互
+ * @create: 2024-07-18 15:30
+ **/
+@ClientEndpoint
+@Slf4j
+public class GateClient {
+
+ private static final String WS_ENDPOINT = "wss://api.gateio.ws/ws/v4/"; // WebSocket 端点 URL
+ private static final long PING_INTERVAL = 20000; // Ping 消息发送间隔,单位毫秒
+
+ private final List<Currency> subscriptions; // 存储要订阅的货币列表
+ private final ScheduledExecutorService executorService; // 定时任务调度服务
+ private Session session; // WebSocket 连接会话
+
+ private final Object lock = new Object(); // 添加一个锁对象
+ private volatile boolean reconnecting = false; // 表示是否正在重连,使用 volatile 保证可见性
+
+ public GateClient(List<Currency> subscriptions) {
+ this.subscriptions = subscriptions; // 初始化订阅的货币
+ this.executorService = Executors.newScheduledThreadPool(1); // 创建一个定时任务调度线程池
+ }
+
+ public void start() {
+ try {
+ connect(); // 尝试连接 WebSocket
+ if (session == null) { // 如果连接失败,session 仍然为 null
+ log.info("无法在超时时间内连接到服务器。");
+ return; // 提前返回
+ }
+
+ // 定期发送 Ping 消息保持连接
+ executorService.scheduleAtFixedRate(this::sendPing, PING_INTERVAL, PING_INTERVAL, TimeUnit.MILLISECONDS);
+
+ // 订阅消息
+ for (Currency subscription : subscriptions) {
+ String parameter = getParameter(subscription.getSymbol()); // 获取订阅参数
+ session.getBasicRemote().sendText(parameter); // 发送订阅请求
+ }
+
+ synchronized (this) { // 进入同步块以等待连接的激活
+ this.wait(); // 等待连接激活的通知
+ }
+
+ } catch (Exception e) {
+ log.error("gate ws 连接过程中发生异常: " + e.getMessage(), e); // 记录连接过程中发生的异常
+ } finally {
+ executorService.shutdown(); // 确保定时任务调度服务被关闭
+ }
+ }
+
+ private void connect() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer(); // 获取 WebSocket 容器
+ container.connectToServer(this, new URI(WS_ENDPOINT)); // 连接到 WebSocket 服务器
+ }
+
+ @OnOpen
+ public void onOpen(Session session) {
+ log.info("gate ws 已连接到服务器。"); // 连接成功日志
+ this.session = session; // 保存会话信息
+ synchronized (this) { // 进入同步块
+ this.notify(); // 通知等待的线程
+ }
+ }
+
+ private static final Gson gson = new Gson(); // 将 Gson 作为静态成员,避免重复实例化
+ private static final String RESULT_KEY = "result"; // 定义结果键的常量
+ private static final String BIDS_KEY = "bids"; // 定义 bids 的常量
+ private static final String ASKS_KEY = "asks"; // 定义 asks 的常量
+ private static final String S_KEY = "s"; // 定义 s 的常量
+
+ @OnMessage
+ public void onMessage(String message) {
+ try {
+ // 解析收到的消息为 Map
+ Map<String, Object> map = gson.fromJson(message, new TypeToken<Map<String, Object>>() {}.getType());
+ Object object = map.get(RESULT_KEY); // 获取结果对象
+ Map<String, Object> resultMap = gson.fromJson(gson.toJson(object), new TypeToken<Map<String, Object>>() {}.getType()); // 直接转换为 Map
+ // 检查结果是否有效,并整合检查
+ if (resultMap != null && resultMap.get(S_KEY) != null) {
+ HashMap<String, Object> hashMap = new HashMap<>(); // 创建新的 HashMap 保存 bids 和 asks
+
+ // 放入 bids 和 asks 数据
+ hashMap.put(BIDS_KEY, resultMap.get(BIDS_KEY)); // 放入 bids 数据
+ hashMap.put(ASKS_KEY, resultMap.get(ASKS_KEY)); // 放入 asks 数据
+
+ String key = "gate" + resultMap.get(S_KEY); // 生成 Redis 键
+ RedisUtil.set(key.replace("_", ""), gson.toJson(hashMap)); // 存入 Redis,使用 Gson 进行序列化
+ }
+ } catch (JsonSyntaxException e) {
+ log.error("JSON 解析异常:" + e.getMessage(), e); // 记录 JSON 解析异常
+ } catch (Exception e) { // 捕获其他可能的异常
+ log.error("处理消息时发生异常:" + e.getMessage(), e); // 记录异常
+ }
+ }
+
+
+ @OnClose
+ public void onClose() {
+ log.info("gate ws 连接已关闭,尝试重新连接..."); // 连接关闭日志
+ handleConnectionClosedOrError(); // 处理连接关闭或错误
+ }
+
+ @OnError
+ public void onError(Throwable throwable) {
+ log.error("gate ws 发生错误: " + throwable.getMessage(), throwable); // 记录错误日志
+ handleConnectionClosedOrError(); // 处理连接关闭或错误
+ }
+
+ private void handleConnectionClosedOrError() {
+ synchronized (lock) { // 进入同步块以防止并发重连
+ if (!reconnecting) { // 检查当前是否已经在重连
+ reconnecting = true; // 设置 reconnecting 为 true 表示开始重连
+ executorService.execute(this::attemptReconnect); // 使用 execute 方法立即执行重连
+ }
+ }
+ }
+
+ private void attemptReconnect() {
+ boolean doReconnect = true; // 是否进行重连的标志
+ try {
+ log.info("gate ws 开始重连"); // 开始重连日志
+ connect(); // 尝试重新连接
+ log.info("gate ws 重连成功"); // 重连成功日志
+ } catch (Exception e) {
+ log.error("gate ws 重连失败", e); // 重连失败记录日志
+ doReconnect = false; // 标记不再继续重连
+ } finally {
+ synchronized (lock) { // 进入同步块
+ if (doReconnect) {
+ scheduleReconnect(); // 如果需要继续重连,调度重连任务
+ } else {
+ reconnecting = false; // 重连结束,标记重连状态为 false
+ }
+ }
+ }
+ }
+
+ private void scheduleReconnect() {
+ if (!executorService.isShutdown()) { // 确保调度服务未关闭
+ executorService.schedule(this::attemptReconnect, 5, TimeUnit.SECONDS); // 重连调度,5秒后尝试重新连接
+ }
+ }
+
+ private void sendPing() {
+ try {
+ if (session != null) { // 检查会话是否存在
+ session.getBasicRemote().sendPing(ByteBuffer.wrap("Ping".getBytes())); // 发送 Ping 消息
+ }
+ } catch (Exception e) {
+ log.error("发送心跳失败", e); // 记录心跳发送失败日志
+ }
+ }
+
+ public String getParameter(String symbol) throws JsonProcessingException, JSONException {
+ // 替换USDT为_USDT
+ symbol = symbol.replaceAll("USDT", "_USDT"); // 替换货币符号中的 USDT
+
+ // 创建一个ObjectMapper实例
+ ObjectMapper mapper = new ObjectMapper(); // 创建 ObjectMapper 实例
+ // 获取当前时间的毫秒数
+ long currentTimeMillis = System.currentTimeMillis(); // 获取当前时间
+
+ // 定义常量
+ final String CHANNEL = "spot.order_book"; // 固定频道名称
+ final String EVENT_SUBSCRIBE = "subscribe"; // 订阅事件
+ final String EVENT_UNSUBSCRIBE = "unsubscribe"; // 取消订阅事件
+ final String[] PAYLOAD = new String[]{symbol, "20", "100ms"}; // 请求负载信息
+
+ // 使用Map构建JSON对象
+ Map<String, Object> jsonMap = new HashMap<>(); // 创建 Map 存放 JSON 内容
+ jsonMap.put("time", currentTimeMillis); // 将当前时间放入 Map
+ jsonMap.put("channel", CHANNEL); // 将频道信息放入 Map
+ jsonMap.put("event", EVENT_SUBSCRIBE); // 事件类型放入 Map
+ jsonMap.put("payload", Arrays.asList(PAYLOAD)); // 将负载数组转为 List 放入 Map
+
+ // 将Map转换为JSON字符串
+ String jsonString = mapper.writeValueAsString(jsonMap); // 转换为 JSON 字符串
+ return jsonString; // 返回 JSON 字符串
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/KucoinClient.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/KucoinClient.java"
new file mode 100644
index 0000000..9e2033c
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/KucoinClient.java"
@@ -0,0 +1,254 @@
+package org.example.wsClient;
+
+import com.alibaba.druid.util.StringUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import lombok.extern.slf4j.Slf4j;
+import org.example.pojo.Currency;
+import org.example.util.RedisUtil;
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONException;
+
+import javax.websocket.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @program: demo
+ * @description: Kucoin WebSocket 客户端
+ * @create: 2024-07-19 16:44
+ **/
+@ClientEndpoint
+@Slf4j
+public class KucoinClient {
+
+ private static final String WS_ENDPOINT = "wss://ws-api-spot.kucoin.com/spotMarket/level2Depth5:"; // WebSocket 端点
+ private static final String CHARSET = "UTF-8"; // 定义字符集常量,避免魔法字符串
+ private static final String PING_MESSAGE = "Ping"; // 心跳消息
+ private static final long PING_INTERVAL = 20000; // 心跳间隔
+ private static final int RECONNECT_DELAY = 5; // 重连间隔
+
+ private final List<Currency> subscriptions; // 订阅的货币列表
+ private final ScheduledExecutorService executorService; // 调度线程池
+ private Session session; // WebSocket会话
+ private String token; // 访问令牌
+ private final Object lock = new Object(); // 锁对象,用于控制重连
+ private volatile boolean reconnecting = false; // 表示当前是否在重连
+
+ private String id; // 当前会话的 ID
+
+ public KucoinClient(List<Currency> subscriptions, String token) {
+ this.subscriptions = subscriptions; // 保存订阅的货币列表
+ this.token = token; // 保存令牌
+ this.executorService = Executors.newScheduledThreadPool(1); // 创建调度线程池
+ }
+
+ public void start() {
+ try {
+ connect(); // 连接到 WebSocket 服务器
+ if (session == null) {
+ log.info("无法在超时时间内连接到服务器。"); // 输出连接失败日志
+ return; // 结束方法
+ }
+
+ // 定期发送心跳
+ executorService.scheduleAtFixedRate(this::sendPing, PING_INTERVAL, PING_INTERVAL, TimeUnit.MILLISECONDS);
+
+ synchronized (this) { // 同步等待连接
+ this.wait(); // 当前线程等待
+ }
+
+ } catch (Exception e) {
+ log.error("kucoin ws 连接过程中发生异常: ", e); // 捕获并记录异常
+ } finally {
+ executorService.shutdown(); // 关闭调度线程池
+ }
+ }
+
+ private void connect() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer(); // 获取 WebSocket 容器
+ String url = generateWebSocketURL(); // 生成 WebSocket URL
+ container.connectToServer(this, new URI(url)); // 连接到 WebSocket 服务器
+ String parameter = subscription(); // 生成订阅消息
+ session.getBasicRemote().sendText(parameter); // 发送订阅消息
+ }
+
+ private String generateWebSocketURL() throws UnsupportedEncodingException {
+ String symbol = getSymbol(); // 获取符号
+ String url = WS_ENDPOINT + symbol + "?token=" + URLEncoder.encode(token, CHARSET); // 构建 WebSocket URL
+ return url; // 返回生成的 URL
+ }
+
+ @OnOpen
+ public void onOpen(Session session) {
+ log.info("kucoin ws 已连接到服务器。"); // 输出连接成功日志
+ this.session = session; // 保存当前会话
+ synchronized (this) { // 同步通知所有等待的线程
+ this.notify();
+ }
+ }
+
+ private static final Gson gson = new Gson(); // Gson 实例,负责 JSON 处理
+
+ @OnMessage
+ public void onMessage(String message) {
+ try {
+ Map<String, Object> map = parseMessage(message); // 解析消息
+ handleMessage(map); // 处理消息
+ } catch (JsonSyntaxException | JsonProcessingException e) {
+ log.error("JSON 解析异常:", e); // 捕获 JSON 解析异常
+ }
+ }
+
+ private Map<String, Object> parseMessage(String message) throws JsonSyntaxException {
+ return gson.fromJson(message, new TypeToken<Map<String, Object>>() {}.getType()); // 解析 JSON 消息
+ }
+
+ private void handleMessage(Map<String, Object> map) throws JsonProcessingException {
+ if (map.get("id") != null) {
+ this.id = map.get("id").toString(); // 设置会话 ID
+ }
+ if (map.get("data") != null) {
+ Object object = map.get("data"); // 获取数据内容
+ processData(map.get("topic").toString(), object); // 处理数据
+ }
+ }
+
+ private static final String PREFIX = "kucoin"; // 创建常量,方便以后修改和维护
+
+ private void processData(String topic, Object object) throws JsonProcessingException {
+ // 将数据解析为 Map
+ Map<String, Object> resultMap = null;
+ try {
+ resultMap = gson.fromJson(object.toString(), new TypeToken<Map<String, Object>>() {}.getType()); // 解析 JSON 对象
+ } catch (JsonSyntaxException e) {
+ log.error("JSON 解析失败: {}", e.getMessage()); // 输出 JSON 解析错误日志
+ return; // 结束方法执行
+ }
+
+ if (resultMap != null) {
+ // 创建线程安全的 HashMap
+ Map<String, Object> hashMap = new ConcurrentHashMap<>();
+ ObjectMapper mapper = new ObjectMapper(); // 创建 ObjectMapper 实例
+
+ // 空值检查,避免存储 null 值到 Redis
+ if (resultMap.get("bids") != null) {
+ hashMap.put("bids", resultMap.get("bids")); // 存储 bids
+ }
+ if (resultMap.get("asks") != null) {
+ hashMap.put("asks", resultMap.get("asks")); // 存储 asks
+ }
+
+ String symbol = extractSymbolFromTopic(topic); // 从 topic 提取符号
+ String key = PREFIX + symbol; // 创建 Redis 缓存键
+ try {
+ RedisUtil.set(key, mapper.writeValueAsString(hashMap)); // 存储到 Redis
+ } catch (JsonProcessingException e) {
+ log.error("将数据存入 Redis 时出错: {}", e.getMessage()); // 输出数据存储错误日志
+ }
+ } else {
+ log.error("topic--->存入redis失败"); // 输出处理失败日志
+ }
+ }
+
+
+ private String extractSymbolFromTopic(String topic) {
+ int index = topic.indexOf(":"); // 找到分隔符的位置
+ if (index != -1) { // 如果找到了分隔符
+ String substring = topic.substring(index + 1);
+ return substring.replaceAll("-", ""); // 返回去掉"-"的符号
+ }
+ return ""; // 未找到分隔符返回空
+ }
+
+ @OnClose
+ public void onClose() {
+ log.info("kucoin ws 连接已关闭,尝试重新连接..."); // 输出连接关闭日志
+ handleConnectionClosedOrError(); // 处理连接关闭或错误
+ }
+
+ @OnError
+ public void onError(Throwable throwable) {
+ log.error("kucoin ws 发生错误: ", throwable); // 输出错误日志
+ handleConnectionClosedOrError(); // 处理连接关闭或错误
+ }
+
+ private void handleConnectionClosedOrError() {
+ synchronized (lock) { // 同步块,确保线程安全
+ if (!reconnecting) {
+ reconnecting = true; // 状态标记为重连中
+ executorService.execute(this::attemptReconnect); // 执行重连操作
+ }
+ }
+ }
+
+ private void attemptReconnect() {
+ try {
+ log.info("kucoin ws 开始重连"); // 输出重连开始日志
+ connect(); // 尝试重新连接
+ log.info("kucoin ws 重连成功"); // 输出重连成功日志
+ } catch (Exception e) {
+ log.error("kucoin ws 重连失败: ", e); // 输出重连失败日志
+ } finally {
+ synchronized (lock) { // 同步块
+ reconnecting = false; // 状态标记为未重连
+ scheduleReconnect(); // 重新调度重连任务
+ }
+ }
+ }
+
+ private void scheduleReconnect() {
+ if (!executorService.isShutdown()) { // 检查线程池是否已经关闭
+ executorService.schedule(this::attemptReconnect, RECONNECT_DELAY, TimeUnit.SECONDS); // 调度重连
+ }
+ }
+
+ private void sendPing() {
+ try {
+ if (session != null) {
+ session.getBasicRemote().sendPing(ByteBuffer.wrap(PING_MESSAGE.getBytes(CHARSET))); // 发送心跳消息
+ }
+ } catch (Exception e) {
+ log.error("发送心跳失败:", e); // 捕获并记录心跳发送失败的异常
+ }
+ }
+
+ public String subscription() throws JsonProcessingException, JSONException {
+ String symbol = getSymbol(); // 获取当前货币符号
+
+ // 创建 Map 构建 JSON 对象
+ Map<String, Object> jsonMap = new HashMap<>();
+ jsonMap.put("id", id); // 会话 ID
+ jsonMap.put("type", "subscribe"); // 订阅类型
+ jsonMap.put("topic", "/spotMarket/level2Depth50:" + symbol); // 订阅的主题
+ jsonMap.put("privateChannel", false); // 是否私有通道
+ jsonMap.put("response", true); // 是否返回响应
+
+ ObjectMapper mapper = new ObjectMapper(); // 创建 ObjectMapper 实例
+ return mapper.writeValueAsString(jsonMap); // 返回 JSON 字符串
+ }
+
+ @NotNull
+ private String getSymbol() {
+ List<String> symbolList = subscriptions.stream()
+ .map(currency -> currency.getSymbol().replaceAll("USDT", "-USDT")) // 替换符号
+ .collect(Collectors.toList()); // 收集符号到列表
+ return String.join(",", symbolList); // 将符号列表转换为 字符串
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/MexcClient.java" "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/MexcClient.java"
new file mode 100644
index 0000000..d93bfb4
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/java/org/example/wsClient/MexcClient.java"
@@ -0,0 +1,176 @@
+package org.example.wsClient;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import lombok.extern.slf4j.Slf4j;
+import org.example.pojo.Currency;
+import org.example.util.RedisUtil;
+
+import javax.websocket.*;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+
+@ClientEndpoint
+@Slf4j
+public class MexcClient {
+ private static final String WS_ENDPOINT = "wss://wbs.mexc.com/ws";
+ private static final long PING_INTERVAL = 20000;
+
+ private final List<Currency> subscriptions;
+ private final ScheduledExecutorService executorService;
+ private Session session;
+
+ private final Object lock = new Object(); // 添加一个锁对象
+ private volatile boolean reconnecting = false; // 使用 volatile 关键字保证可见性
+
+ public MexcClient(List<Currency> subscriptions) {
+ this.subscriptions = subscriptions;
+ this.executorService = Executors.newScheduledThreadPool(1);
+ }
+
+ public void start() {
+ try {
+ connect();
+ if (session == null) {
+ log.info("无法在超时时间内连接到服务器。");
+ return;
+ }
+
+ executorService.scheduleAtFixedRate(this::sendPing, PING_INTERVAL, PING_INTERVAL, TimeUnit.MILLISECONDS);
+
+ // 订阅消息
+ for (Currency subscription : subscriptions) {
+ String parameter = getParameter(subscription.getSymbol());
+ session.getBasicRemote().sendText(parameter);
+ }
+
+ synchronized (this) {
+ this.wait();
+ }
+
+ } catch (Exception e) {
+ log.error("mexc ws 连接过程中发生异常: " + e.getMessage(), e);
+ } finally {
+ executorService.shutdown();
+ }
+ }
+
+ private void connect() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+ container.connectToServer(this, new URI(WS_ENDPOINT));
+ }
+
+ @OnOpen
+ public void onOpen(Session session) {
+ log.info("mexc ws 已连接到服务器。");
+ this.session = session;
+ synchronized (this) {
+ this.notify();
+ }
+ }
+ private static final Gson gson = new Gson(); // 将 Gson 作为静态成员或单例
+
+ @OnMessage
+ public void onMessage(String message) {
+ try {
+ Map<String, Object> map = gson.fromJson(message, new TypeToken<Map<String, Object>>() {}.getType());
+ if (map != null && map.containsKey("s")) {
+ Object object = map.get("d");
+ Map<String, Object> resultMap = gson.fromJson(object.toString(), new TypeToken<Map<String, Object>>() {}.getType());
+ HashMap<String,Object> hashMap = new HashMap<>();
+ ObjectMapper mapper = new ObjectMapper();
+ hashMap.put("bids",resultMap.get("bids"));
+ hashMap.put("asks",resultMap.get("asks"));
+ String key = "mexc" + map.get("s").toString();
+ RedisUtil.set(key, mapper.writeValueAsString(hashMap));
+ }
+ } catch (JsonSyntaxException e) {
+ log.error("JSON 解析异常:" + e.getMessage(), e);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @OnClose
+ public void onClose() {
+ log.info("mexc ws 连接已关闭,尝试重新连接...");
+ handleConnectionClosedOrError();
+ }
+
+ @OnError
+ public void onError(Throwable throwable) {
+ log.error("mexc ws 发生错误: " + throwable.getMessage(), throwable);
+ handleConnectionClosedOrError();
+ }
+
+ private void handleConnectionClosedOrError() {
+ synchronized (lock) {
+ if (!reconnecting) {
+ reconnecting = true; // 设置 reconnecting 为 true 表示开始重连
+ executorService.execute(this::attemptReconnect); // 使用 execute 方法立即执行重连
+ }
+ }
+ }
+
+ private void attemptReconnect() {
+ boolean doReconnect = true;
+ try {
+ log.info("mexc ws 开始重连");
+ connect(); // 假设 connect() 方法用于实际的连接逻辑
+ log.info("mexc ws 重连成功");
+ } catch (Exception e) {
+ log.error("mexc ws 重连失败", e);
+ // 连接失败时,可以根据具体情况决定是否继续重连
+ // 在这里假设总是继续尝试重连
+ } finally {
+ synchronized (lock) {
+ if (doReconnect) {
+ scheduleReconnect(); // 如果需要继续重连,则重新调度重连任务
+ } else {
+ reconnecting = false; // 重连结束后设置 reconnecting 为 false
+ }
+ }
+ }
+ }
+
+ private void scheduleReconnect() {
+ if (!executorService.isShutdown()) {
+ executorService.schedule(this::attemptReconnect, 5, TimeUnit.SECONDS);
+ }
+ }
+
+ private void sendPing() {
+ try {
+ if (session != null) {
+ session.getBasicRemote().sendPing(ByteBuffer.wrap("Ping".getBytes()));
+ }
+ } catch (Exception e) {
+ log.error("发送心跳失败", e);
+ }
+ }
+
+ public String getParameter(String symbol) throws JsonProcessingException {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode root = mapper.createObjectNode();
+
+ root.put("method", "SUBSCRIPTION");
+ ArrayNode paramsArray = mapper.createArrayNode();
+ String customParam = String.format("spot@public.limit.depth.v3.api@%s@20", symbol);
+ paramsArray.add(customParam);
+ root.set("params", paramsArray);
+
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
+ }
+}
diff --git "a/mexcClient-\345\272\237\345\274\203/src/main/resources/application.yml" "b/mexcClient-\345\272\237\345\274\203/src/main/resources/application.yml"
new file mode 100644
index 0000000..b0ce469
--- /dev/null
+++ "b/mexcClient-\345\272\237\345\274\203/src/main/resources/application.yml"
@@ -0,0 +1,75 @@
+server:
+ port: 8084
+
+
+spring:
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 1
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 99
+ # 连接池的最大数据库连接数
+ max-active: 99
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+
+ druid:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: Greysparrow
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: false
diff --git a/mexcClient/.gitignore b/mexcClient/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/mexcClient/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/mexcClient/pom.xml b/mexcClient/pom.xml
new file mode 100644
index 0000000..19d4e6f
--- /dev/null
+++ b/mexcClient/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.example</groupId>
+ <artifactId>mexcClient</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>mexcClient</name>
+ <description>mexcClient</description>
+ <properties>
+ <java.version>1.8</java.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <spring-boot.version>2.6.13</spring-boot.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version> <!-- 根据需要选择最新的版本 -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>20.0</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>3.4.3.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <dependency>
+ <groupId>io.socket</groupId>
+ <artifactId>engine.io-client</artifactId>
+ <version>2.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mybatis.spring.boot</groupId>
+ <artifactId>mybatis-spring-boot-starter</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>3.7.0</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ <configuration>
+ <mainClass>org.example.mexcclient.MexcClientApplication</mainClass>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>repackage</id>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/mexcClient/src/main/java/org/example/mexcclient/MexcClientApplication.java b/mexcClient/src/main/java/org/example/mexcclient/MexcClientApplication.java
new file mode 100644
index 0000000..c83ac19
--- /dev/null
+++ b/mexcClient/src/main/java/org/example/mexcclient/MexcClientApplication.java
@@ -0,0 +1,13 @@
+package org.example.mexcclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MexcClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MexcClientApplication.class, args);
+ }
+
+}
diff --git a/mexcClient/src/main/resources/application.yml b/mexcClient/src/main/resources/application.yml
new file mode 100644
index 0000000..b0ce469
--- /dev/null
+++ b/mexcClient/src/main/resources/application.yml
@@ -0,0 +1,75 @@
+server:
+ port: 8084
+
+
+spring:
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 1
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 99
+ # 连接池的最大数据库连接数
+ max-active: 99
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+
+ druid:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: Greysparrow
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: false
diff --git a/mexcClient/src/main/resources/static/index.html b/mexcClient/src/main/resources/static/index.html
new file mode 100644
index 0000000..89bb8ba
--- /dev/null
+++ b/mexcClient/src/main/resources/static/index.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<h1>hello word!!!</h1>
+<p>this is a html page</p>
+</body>
+</html>
\ No newline at end of file
--
Gitblit v1.9.3