Browse Source

add:coin init

lvzhiqiang 2 years ago
parent
commit
82a29f9d54

+ 6 - 0
pom.xml

@@ -125,6 +125,12 @@
             <version>1.14.3</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.8</version>
+        </dependency>
+
         <!-- https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2 -->
         <dependency>
             <groupId>ch.ethz.ganymed</groupId>

+ 35 - 0
src/main/java/top/lvzhiqiang/controller/CoinController.java

@@ -0,0 +1,35 @@
+package top.lvzhiqiang.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import top.lvzhiqiang.service.CoinService;
+
+import javax.annotation.Resource;
+
+/**
+ * Coin Controller
+ *
+ * @author lvzhiqiang
+ * 2023/9/5 15:23
+ */
+@Controller
+@RequestMapping("/bg/coin")
+public class CoinController {
+
+    @Resource
+    private CoinService coinService;
+
+    /**
+     * 获取全部合约仓位信息V2
+     *
+     * @author lvzhiqiang
+     * 2023/9/5 15:23
+     */
+    @RequestMapping("/findAllPositionv2")
+    @ResponseBody
+    public String findAllPositionv2() {
+
+        return coinService.findAllPositionv2();
+    }
+}

+ 20 - 0
src/main/java/top/lvzhiqiang/service/CoinService.java

@@ -0,0 +1,20 @@
+package top.lvzhiqiang.service;
+
+/**
+ * Coin Service
+ *
+ * @author lvzhiqiang
+ * 2023/9/5 15:23
+ */
+public interface CoinService {
+
+    String monitorJob();
+
+    /**
+     * 获取全部合约仓位信息V2
+     *
+     * @author lvzhiqiang
+     * 2023/9/5 15:23
+     */
+    String findAllPositionv2();
+}

+ 155 - 0
src/main/java/top/lvzhiqiang/service/impl/CoinServiceImpl.java

@@ -0,0 +1,155 @@
+package top.lvzhiqiang.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jsoup.Connection;
+import org.springframework.stereotype.Service;
+import top.lvzhiqiang.service.CoinService;
+import top.lvzhiqiang.util.CheckSign4Bitget;
+import top.lvzhiqiang.util.DateUtils;
+import top.lvzhiqiang.util.JsoupUtil;
+
+import java.io.UnsupportedEncodingException;
+import java.net.Proxy;
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Coin ServiceImpl
+ *
+ * @author lvzhiqiang
+ * 2023/9/5 15:23
+ */
+@Service
+@Slf4j
+public class CoinServiceImpl implements CoinService {
+    // 所有REST请求的header都必须包含以下key:
+    private static final Map<String, String> basicHeaderMap = new HashMap<>();
+    // 主域名 URL
+    private static final String mainUrl = "https://api.bitget.com";
+    // 私钥,由系统随机生成,用于签名的生成。
+    private static final String secretKey = "1fdd0fc2976bea80189ba13710e12825ca3ef6c5e25a0d76fd03f8f6cd4a61d9";
+
+    static {
+        // API KEY作为一个字符串。
+        basicHeaderMap.put("ACCESS-KEY", "bg_433d37306df0e8901c6d107c6d9e9111");
+        // 使用base64编码签名(请参阅签名消息)。
+        basicHeaderMap.put("ACCESS-SIGN", "");
+        // 您请求的时间戳。
+        basicHeaderMap.put("ACCESS-TIMESTAMP", "");
+        // 您在创建API KEY时设置的口令。
+        basicHeaderMap.put("ACCESS-PASSPHRASE", "7f934f62f2701bee932204580d115228");
+        // 统一设置为application/json。
+        basicHeaderMap.put("Content-Type", "application/json");
+        // 支持多语言, 如:中文(zh-CN),英语(en-US)
+        basicHeaderMap.put("locale", "zh-CN");
+    }
+
+
+    @Override
+    public String monitorJob() {
+
+        return null;
+    }
+
+    /**
+     * 获取全部合约仓位信息V2
+     *
+     * @author lvzhiqiang
+     * 2023/9/5 15:23
+     */
+    @Override
+    public String findAllPositionv2() {
+        JSONObject result = handleAllPositionV2();
+        JSONArray data = result.getJSONArray("data");
+
+        StringBuffer sb = new StringBuffer("total:".concat(String.valueOf(data.size())).concat("<br/>"));
+        sb.append("<table border=\"1\" cellspacing=\"0\"><tr>");
+        sb.append("<th>币对名称</th>");
+        sb.append("<th>保证金币种</th>");
+        sb.append("<th>持仓方向</th>");
+        sb.append("<th>当前委托待成交的数量</th>");
+        sb.append("<th>保证金数量</th>");
+        sb.append("<th>自动追加保证金</th>");
+        sb.append("<th>仓位可用</th>");
+        sb.append("<th>仓位冻结</th>");
+        sb.append("<th>仓位总数量</th>");
+        sb.append("<th>杠杆倍数</th>");
+        sb.append("<th>已实现盈亏</th>");
+        sb.append("<th>平均开仓价</th>");
+        sb.append("<th>保证金模式</th>");
+        sb.append("<th>持仓模式</th>");
+        sb.append("<th>未实现盈亏</th>");
+        sb.append("<th>预估强平价</th>");
+        sb.append("<th>维持保证金率</th>");
+        sb.append("<th>标记价格</th>");
+        sb.append("<th>最近更新时间</th>");
+        sb.append("</tr>");
+
+        for (int i = 0; i < data.size(); i++) {
+            JSONObject jsonObject = data.getJSONObject(i);
+            sb.append("<tr>");
+
+            sb.append("<td>").append(jsonObject.getString("symbol")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("marginCoin")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("holdSide")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("openDelegateCount")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("margin")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("autoMargin")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("available")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("locked")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("total")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("leverage")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("achievedProfits")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("averageOpenPrice")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("marginMode")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("holdMode")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("unrealizedPL")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("liquidationPrice")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("keepMarginRate")).append("</td>");
+            sb.append("<td>").append(jsonObject.getString("marketPrice")).append("</td>");
+            sb.append("<td>").append(DateUtils.timeToString(jsonObject.getLong("cTime"))).append("</td>");
+
+            sb.append("</tr>");
+        }
+        sb.append("</table>");
+
+        return sb.toString();
+    }
+
+    /**
+     * 处理全部合约仓位信息V2
+     */
+    private JSONObject handleAllPositionV2() {
+        String requestPath = "/api/mix/v1/position/allPosition-v2";
+        String timestamp = String.valueOf(System.currentTimeMillis());
+        String queryString = "productType=umcbl";
+        Map<String, String> headerMap = new HashMap<>();
+        headerMap.putAll(basicHeaderMap);
+        try {
+            String accessSign = CheckSign4Bitget.generate(timestamp, "GET", requestPath, queryString, null, secretKey);
+            headerMap.put("ACCESS-TIMESTAMP", timestamp);
+            headerMap.put("ACCESS-SIGN", accessSign);
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException(e);
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+        Map<String, String> paramMap = new HashMap<>();
+        paramMap.put("productType", "umcbl");
+        try {
+            String requestUrl = mainUrl + requestPath;
+            //Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
+            Connection.Response response = JsoupUtil.requestBody(requestUrl, JsoupUtil.HTTP_GET, Proxy.NO_PROXY, headerMap, paramMap);
+
+            return JSONObject.parseObject(response.body());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 61 - 0
src/main/java/top/lvzhiqiang/util/CheckSign4Bitget.java

@@ -0,0 +1,61 @@
+package top.lvzhiqiang.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.management.RuntimeErrorException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+@Slf4j
+public class CheckSign4Bitget {
+    private static final String secretKey = "";
+
+    public static void main(String[] args) throws Exception {
+        //POST sign example
+//        String timestamp = "1684813405151";
+//        String body = "{\"symbol\":\"TRXUSDT_UMCBL\",\"marginCoin\":\"USDT\",\"size\":551,\"side\":\"open_long\",\"orderType\":\"limit\",\"price\":0.0555,\"timeInForceValue\":\"normal\"}";
+//
+//        String sign = generate(timestamp,"POST","/api/mix/v1/order/placeOrder" ,null,body,secretKey);
+//        log.info("sign:{}",sign);
+
+
+        //GET sign example
+        String timestamp = "1684814440729";
+        String queryString = "symbol=btcusdt_umcbl&marginCoin=usdt";
+        String sign = generate(timestamp, "GET", "/api/mix/v1/account/account", queryString, null, secretKey);
+        log.info("sign:{}", sign);
+    }
+
+
+    private static Mac MAC;
+
+    static {
+        try {
+            CheckSign4Bitget.MAC = Mac.getInstance("HmacSHA256");
+        } catch (NoSuchAlgorithmException var1) {
+            throw new RuntimeErrorException(new Error("Can't get Mac's instance."));
+        }
+    }
+
+    public static String generate(String timestamp, String method, String requestPath,
+                                  String queryString, String body, String secretKey)
+            throws CloneNotSupportedException, InvalidKeyException, UnsupportedEncodingException {
+
+        method = method.toUpperCase();
+        body = StringUtils.defaultIfBlank(body, StringUtils.EMPTY);
+        queryString = StringUtils.isBlank(queryString) ? StringUtils.EMPTY : "?" + queryString;
+        String preHash = timestamp + method + requestPath + queryString + body;
+        log.info("preHash:{}", preHash);
+        byte[] secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
+        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyBytes, "HmacSHA256");
+        Mac mac = (Mac) CheckSign4Bitget.MAC.clone();
+        mac.init(secretKeySpec);
+        return Base64.getEncoder().encodeToString(mac.doFinal(preHash.getBytes(StandardCharsets.UTF_8)));
+    }
+}

+ 12 - 0
src/main/java/top/lvzhiqiang/util/DateUtils.java

@@ -14,8 +14,10 @@ package top.lvzhiqiang.util;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
 import java.util.Date;
@@ -344,6 +346,16 @@ public class DateUtils {
         return System.currentTimeMillis();
     }
 
+    /**
+     * 将Long类型的时间戳转换成String 类型的时间格式,时间格式为:yyyy-MM-dd HH:mm:ss
+     *
+     * @param time
+     * @return
+     */
+    public static String timeToString(Long time) {
+        return dateTimeFormatter.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
+    }
+
     public static void main(String[] args) {
         System.out.println(getFewDateStrsByMonth(getToday(), 7));
     }

+ 326 - 0
src/main/java/top/lvzhiqiang/util/HttpUtils.java

@@ -0,0 +1,326 @@
+package top.lvzhiqiang.util;
+
+import com.alibaba.fastjson.JSONException;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.util.*;
+
+/**
+ * HTTP工具类
+ *
+ * @author shiyong
+ * 2019-12-17 16:08
+ */
+public class HttpUtils {
+
+    // 编码格式。发送编码格式统一用UTF-8
+    private static final String ENCODING = "UTF-8";
+
+    // 设置连接超时时间,单位毫秒。ConnectTimeoutException
+    private static final int CONNECT_TIMEOUT = 60000;
+
+    // 请求获取数据的超时时间(即响应时间),单位毫秒。如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。SocketTimeoutException
+    private static final int SOCKET_TIMEOUT = 30000;
+
+    // 设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。ConnectionPoolTimeout
+    private static final int CONNECTION_REQUEST_TIMEOUT = 60000;
+
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+    private static CloseableHttpClient httpClient = null;
+
+    /**
+     * 自己构建httpclient连接池。通过享元模式来解决该问题来解决HttpClient引起的TCP连接数高问题
+     *
+     * @return
+     */
+    public static synchronized CloseableHttpClient getHttpClient() {
+        if (httpClient == null) {
+            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
+            // 连接池最大连接数,默认为20
+            cm.setMaxTotal(2000);
+            // 单条链路最大连接数(一个ip+一个端口是一个链路),即每个主机的最大连接数,默认为2
+            cm.setDefaultMaxPerRoute(1000);
+
+            ConnectionKeepAliveStrategy kaStrategy = new DefaultConnectionKeepAliveStrategy() {
+                @Override
+                public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
+                    long keepAlive = super.getKeepAliveDuration(response, context);
+                    if (keepAlive == -1) {
+                        keepAlive = 60000;
+                    }
+                    return keepAlive;
+                }
+            };
+
+            httpClient = HttpClients.custom().setConnectionManager(cm).setKeepAliveStrategy(kaStrategy).build();
+        }
+
+        return httpClient;
+    }
+
+    /**
+     * 发送get请求,返回字符串
+     *
+     * @param url 请求地址
+     * @return java.lang.String
+     * @author shiyong
+     * 2020/4/15 10:54
+     */
+    public static String doGetToStr(String url) throws IOException, URISyntaxException {
+        return doGetToStr(url, new HashMap<>());
+    }
+
+    /**
+     * 发送get请求,返回字符串
+     *
+     * @param url    请求地址
+     * @param params 请求参数
+     * @return java.lang.String
+     * @author shiyong
+     * 2020/4/15 10:58
+     */
+    public static String doGetToStr(String url, Map<String, String> params) throws IOException, URISyntaxException {
+        return doGetToStr(url, new HashMap<>(), params);
+    }
+
+    /**
+     * 发送get请求,返回字符串
+     *
+     * @param url     请求地址
+     * @param headers 请求头
+     * @param params  请求参数
+     * @return java.lang.String
+     * @author shiyong
+     * 2020/4/15 10:59
+     */
+    public static String doGetToStr(String url, Map<String, String> headers, Map<String, String> params) throws IOException, URISyntaxException {
+        // 创建httpClient对象
+        // CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpClient httpClient = getHttpClient();
+
+        // 创建httpResponse对象
+        CloseableHttpResponse httpResponse = null;
+        HttpGet httpGet = null;
+        try {
+            // 创建访问的地址
+            URIBuilder uriBuilder = new URIBuilder(url);
+
+            if (params != null) {
+                Set<Map.Entry<String, String>> entrySet = params.entrySet();
+
+                for (Map.Entry<String, String> entry : entrySet) {
+                    uriBuilder.setParameter(entry.getKey(), entry.getValue());
+                }
+            }
+
+            // 创建http对象
+            httpGet = new HttpGet(uriBuilder.build());
+
+            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
+            httpGet.setConfig(requestConfig);
+
+            // 设置请求头
+            packageHeader(headers, httpGet);
+
+            // 执行请求
+            httpResponse = httpClient.execute(httpGet);
+
+            if (null == httpResponse || null == httpResponse.getStatusLine() || null == httpResponse.getEntity() || httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+                return "";
+            }
+
+            return EntityUtils.toString(httpResponse.getEntity(), ENCODING);
+        } catch (JSONException e) {
+            throw new JSONException(e.getMessage());
+        } catch (IOException e) {
+            throw new IOException(e);
+        } finally {
+            // 释放资源
+            if (httpGet != null) {
+                httpGet.abort();
+                httpGet.releaseConnection();
+            }
+            release(httpResponse, httpClient);
+        }
+    }
+
+
+    /**
+     * 发送post请求,返回字符串
+     *
+     * @param url     请求地址
+     * @param headers 请求头
+     * @param params  请求参数
+     * @return java.lang.String
+     * @author shiyong
+     * 2020/4/15 11:35
+     */
+    public static String doPostToStr(String url, Map<String, String> headers, Map<String, String> params) throws IOException, JSONException {
+        // 创建httpClient对象
+        // CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpClient httpClient = getHttpClient();
+
+        // 创建httpResponse对象
+        CloseableHttpResponse httpResponse = null;
+        HttpPost httpPost = null;
+        try {
+            // 创建http对象
+            httpPost = new HttpPost(url);
+
+            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
+            httpPost.setConfig(requestConfig);
+            //httpPost.setHeader(HttpHeaders.CONNECTION, "close");
+
+            packageHeader(headers, httpPost);
+
+            // 封装请求参数
+            packageParam(params, httpPost);
+
+            // 执行请求
+            httpResponse = httpClient.execute(httpPost);
+
+            if (null == httpResponse || null == httpResponse.getStatusLine() || null == httpResponse.getEntity() || httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+                return "";
+            }
+
+            return EntityUtils.toString(httpResponse.getEntity(), ENCODING);
+        } catch (JSONException e) {
+            throw new JSONException(e.getMessage());
+        } catch (IOException e) {
+            throw new IOException(e);
+        } finally {
+            // 释放资源
+            if (httpPost != null) {
+                httpPost.abort();
+                httpPost.releaseConnection();
+            }
+            release(httpResponse, httpClient);
+        }
+    }
+
+    /**
+     * 发送post请求,返回JSONObject
+     *
+     * @param url    请求地址
+     * @param params 参数集合
+     * @return com.alibaba.fastjson.JSONObject
+     * @author shiyong
+     * 2019/11/23 18:39
+     */
+    public static JSONObject doPost(String url, Map<String, String> params) throws IOException {
+        return doPost(url, new HashMap<String, String>(), params);
+    }
+
+    /**
+     * 发送post请求,返回JSONObject
+     *
+     * @param url     请求地址
+     * @param headers 请求头
+     * @param params  请求参数
+     * @return com.alibaba.fastjson.JSONObject
+     * @author shiyong
+     * 2019/11/23 18:35
+     */
+    public static JSONObject doPost(String url, Map<String, String> headers, Map<String, String> params) throws IOException {
+        String content = doPostToStr(url, headers, params);
+
+        if (StringUtils.isEmpty(content)) {
+            return new JSONObject();
+        }
+
+        return JSONObject.parseObject(content);
+    }
+
+    /**
+     * 封装请求头
+     *
+     * @param params     请求头
+     * @param httpMethod 请求方式
+     * @author shiyong
+     * 2019/11/23 19:21
+     */
+    private static void packageHeader(Map<String, String> params, HttpRequestBase httpMethod) {
+        if (params != null) {
+            Set<Map.Entry<String, String>> entrySet = params.entrySet();
+
+            for (Map.Entry<String, String> entry : entrySet) {
+                // 设置到请求头到HttpRequestBase对象中
+                httpMethod.setHeader(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    /**
+     * 封装请求参数
+     *
+     * @param params     请求参数
+     * @param httpMethod 请求方式
+     * @author shiyong
+     * 2019/11/23 19:22
+     */
+    private static void packageParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod) throws UnsupportedEncodingException {
+        if (params != null) {
+            List<NameValuePair> nvps = new ArrayList<>();
+
+            Set<Map.Entry<String, String>> entrySet = params.entrySet();
+
+            for (Map.Entry<String, String> entry : entrySet) {
+                nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+            }
+
+            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, ENCODING);
+            formEntity.setContentType(URLEncodedUtils.CONTENT_TYPE);
+
+            // 设置到请求的http对象中
+            httpMethod.setEntity(formEntity);
+        }
+    }
+
+    /**
+     * 释放资源
+     *
+     * @param httpResponse HTTP响应
+     * @param httpClient   HTTP客户端
+     * @author shiyong
+     * 2019/11/23 19:28
+     */
+    private static void release(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient) {
+        try {
+            if (httpResponse != null) {
+                httpResponse.close();
+            }
+
+            // 连接池使用的时候不能关闭连接,否则下次使用会抛异常 java.lang.IllegalStateException: Connection pool shut down
+            // 选择使用连接池,就是将连接全部交由连接池管理,而我们在程序中使用了httpClient.close()就破坏了这以规则
+            /*if (httpClient != null) {
+                httpClient.close();
+            }*/
+        } catch (IOException e) {
+            log.error("释放HTTP请求资源失败!", e);
+        }
+
+    }
+
+}

+ 21 - 1
src/main/java/top/lvzhiqiang/util/JsoupUtil.java

@@ -1,5 +1,6 @@
 package top.lvzhiqiang.util;
 
+import com.alibaba.fastjson.JSON;
 import org.jsoup.Connection;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
@@ -24,7 +25,8 @@ public class JsoupUtil {
                 .proxy(proxy)
                 .userAgent(getUserAgent())
                 .followRedirects(true)
-                .ignoreContentType(true);
+                .ignoreContentType(true)
+                .ignoreHttpErrors(true);
     }
 
     public static Document requestDocument(String url, String httpMethod, Proxy proxy, Map<String, String> cookies, Map<String, String> headers, Map<String, String> data) throws Exception {
@@ -66,6 +68,24 @@ public class JsoupUtil {
         return res;
     }
 
+    public static Connection.Response requestBodyJSON(String url, String httpMethod, Proxy proxy, Map<String, String> cookies, Map<String, String> headers, Map<String, String> data) throws Exception {
+        Connection connection = getConnection(url, proxy);
+        if (data != null && data.size() > 0) {
+            connection.header("Content-Type", "application/json");
+            connection.data("a", "b");
+            connection.requestBody(JSON.toJSONString(data));
+        }
+        if (cookies != null) {
+            connection.cookies(cookies);
+        }
+        if (headers != null) {
+            connection.headers(headers);
+        }
+        connection.method(HTTP_POST.equalsIgnoreCase(httpMethod) ? Connection.Method.POST : Connection.Method.GET);
+        Connection.Response res = connection.execute();
+        return res;
+    }
+
     public static Connection.Response requestBody(String url, String httpMethod, Proxy proxy, Map<String, String> data) throws Exception {
         return requestBody(url, httpMethod, proxy, null, null, data);
     }

+ 1 - 1
src/main/resources/env/dev/log4j2-spring.xml

@@ -12,7 +12,7 @@
         <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
 
         <!--定义日志文件存储的基础路径和文件名。因为 Spring Boot 并未提供 Log4j2 拓展,无法直接读取 Spring Boot 配置文件,所以这里我们只能直接定义-->
-        <Property name="FILE_PATH" value="D:\logs\l1024v-jav"/>
+        <Property name="FILE_PATH" value="./logs"/>
         <property name="FILE_NAME" value="jav"/>
 
         <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符,%logger{36} 表示 Logger 名字最长36个字符 -->

+ 40 - 0
src/main/resources/static/coin.html

@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>CRAWLER HOME</title>
+    <meta name="referrer" content="no-referrer"/>
+</head>
+<style type="text/css">
+    .font {
+        color: blue;
+    }
+
+    .dynamic_hide {
+        display: none;
+    }
+</style>
+<script type="text/javascript">
+    function show() {
+        var my = document.getElementById("my");
+        if (my.className.indexOf("dynamic_hide") > -1) {
+            my.classList.remove("dynamic_hide");
+        } else {
+            my.classList.add("dynamic_hide");
+        }
+
+    }
+</script>
+<body>
+<span>Hello <font id="myc" style="cursor: pointer;" onclick="show()">W</font>orld!</span>
+<div id="my" class="dynamic_hide">
+    <hr/>
+    <div style="margin-right:20px;">
+        <span class="font">获取全部合约仓位信息V2</span>
+        <form method="post" action="bg/coin/findAllPositionv2">
+            <input type="submit" value="提交">
+        </form>
+    </div>
+</div>
+</body>
+</html>

+ 1 - 0
src/main/resources/static/index.html

@@ -28,6 +28,7 @@
                 <li><a href="video.html">VIDEO</a></li>
                 <li><a href="bg.html">BG</a></li>
                 <li><a href="crawler.html">CRAWLER</a></li>
+                <li><a href="coin.html">COIN</a></li>
             </ul>
         </nav>
     </header>