|
|
@@ -0,0 +1,488 @@
|
|
|
+package com.jzg.quotation.dadi.crawler.network;
|
|
|
+
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpResponse;
|
|
|
+import cn.hutool.http.Method;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.jzg.quotation.dadi.utils.DaDiAESUtil;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.http.util.TextUtils;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author Liub
|
|
|
+ * @version 1.0
|
|
|
+ * @description: 【大地财险】网络请求基类 - 基于Hutool工具类封装
|
|
|
+ * @date 2026/5/22 08:30
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class NetworkRequest {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认超时时间(毫秒)
|
|
|
+ */
|
|
|
+ private static final int DEFAULT_TIMEOUT = 120000;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 公共请求头(所有请求自动携带)
|
|
|
+ */
|
|
|
+ private static final Map<String, String> COMMON_HEADERS = new LinkedHashMap<>();
|
|
|
+
|
|
|
+ static {
|
|
|
+ COMMON_HEADERS.put(HttpHeaders.CONNECTION, "Keep-Alive");
|
|
|
+ COMMON_HEADERS.put(HttpHeaders.USER_AGENT, "okhttp/3.12.0");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前登录Token(登录后通过setToken()设置)
|
|
|
+ */
|
|
|
+ private String token;
|
|
|
+
|
|
|
+ // ==================== 公共请求头 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置登录Token
|
|
|
+ *
|
|
|
+ * @param token 登录返回的X-Access-Token
|
|
|
+ */
|
|
|
+ public void setToken(String token) {
|
|
|
+ this.token = token;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前Token
|
|
|
+ *
|
|
|
+ * @return 当前Token
|
|
|
+ */
|
|
|
+ public String getToken() {
|
|
|
+ return token;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取包含公共请求头和Token的HttpHeaders
|
|
|
+ *
|
|
|
+ * @return HttpHeaders(可变,调用方可追加自定义header)
|
|
|
+ */
|
|
|
+ public HttpHeaders getDefaultHeaders() {
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ COMMON_HEADERS.forEach(headers::set);
|
|
|
+ headers.set(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8");
|
|
|
+ if (getToken() != null && !getToken().isEmpty()) {
|
|
|
+ headers.set("X-Access-Token", getToken());
|
|
|
+ }
|
|
|
+ return headers;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== GET 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * GET请求(无参)
|
|
|
+ */
|
|
|
+ public String doGet(String url) {
|
|
|
+ return doGet(url, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * GET请求(带参数)
|
|
|
+ */
|
|
|
+ public String doGet(String url, Map<String, Object> params) {
|
|
|
+ return doGet(url, params, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * GET请求(带参数和请求头)
|
|
|
+ */
|
|
|
+ public String doGet(String url, Map<String, Object> params, HttpHeaders headers) {
|
|
|
+ return execute(Method.GET, url, params, null, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== POST 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(无参)
|
|
|
+ */
|
|
|
+ public String doPost(String url) {
|
|
|
+ return doPost(url, (String) null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(JSON字符串体)
|
|
|
+ */
|
|
|
+ public String doPost(String url, String body) {
|
|
|
+ return doPost(url, body, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(JSON字符串体 + 请求头)
|
|
|
+ */
|
|
|
+ public String doPost(String url, String body, HttpHeaders headers) {
|
|
|
+ return execute(Method.POST, url, null, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(对象自动转JSON)
|
|
|
+ */
|
|
|
+ public String doPost(String url, Object bodyObj) {
|
|
|
+ return doPost(url, bodyObj, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(对象自动转JSON + 请求头)
|
|
|
+ */
|
|
|
+ public String doPost(String url, Object bodyObj, HttpHeaders headers) {
|
|
|
+ String body = bodyObj instanceof String ? (String) bodyObj : JSONUtil.toJsonStr(bodyObj);
|
|
|
+ return doPost(url, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== POST Form 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST表单请求(表单参数)
|
|
|
+ */
|
|
|
+ public String doPostForm(String url, Map<String, Object> formParams) {
|
|
|
+ return doPostForm(url, formParams, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST表单请求(表单参数 + 请求头)
|
|
|
+ */
|
|
|
+ public String doPostForm(String url, Map<String, Object> formParams, HttpHeaders headers) {
|
|
|
+ return executeForm(Method.POST, url, formParams, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== PUT 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PUT请求(无参)
|
|
|
+ */
|
|
|
+ public String doPut(String url) {
|
|
|
+ return doPut(url, (String) null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PUT请求(JSON字符串体)
|
|
|
+ */
|
|
|
+ public String doPut(String url, String body) {
|
|
|
+ return doPut(url, body, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PUT请求(JSON字符串体 + 请求头)
|
|
|
+ */
|
|
|
+ public String doPut(String url, String body, HttpHeaders headers) {
|
|
|
+ return execute(Method.PUT, url, null, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PUT请求(对象自动转JSON)
|
|
|
+ */
|
|
|
+ public String doPut(String url, Object bodyObj) {
|
|
|
+ return doPut(url, bodyObj, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PUT请求(对象自动转JSON + 请求头)
|
|
|
+ */
|
|
|
+ public String doPut(String url, Object bodyObj, HttpHeaders headers) {
|
|
|
+ String body = bodyObj instanceof String ? (String) bodyObj : JSONUtil.toJsonStr(bodyObj);
|
|
|
+ return doPut(url, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== DELETE 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * DELETE请求(无参)
|
|
|
+ */
|
|
|
+ public String doDelete(String url) {
|
|
|
+ return doDelete(url, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * DELETE请求(带参数)
|
|
|
+ */
|
|
|
+ public String doDelete(String url, Map<String, Object> params) {
|
|
|
+ return doDelete(url, params, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * DELETE请求(带参数和请求头)
|
|
|
+ */
|
|
|
+ public String doDelete(String url, Map<String, Object> params, HttpHeaders headers) {
|
|
|
+ return execute(Method.DELETE, url, params, null, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== PATCH 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PATCH请求
|
|
|
+ */
|
|
|
+ public String doPatch(String url, String body) {
|
|
|
+ return doPatch(url, body, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * PATCH请求(带请求头)
|
|
|
+ */
|
|
|
+ public String doPatch(String url, String body, HttpHeaders headers) {
|
|
|
+ return execute(Method.PATCH, url, null, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== HEAD 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HEAD请求
|
|
|
+ */
|
|
|
+ public String doHead(String url) {
|
|
|
+ return doHead(url, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HEAD请求(带请求头)
|
|
|
+ */
|
|
|
+ public String doHead(String url, HttpHeaders headers) {
|
|
|
+ return execute(Method.HEAD, url, null, null, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== OPTIONS 请求 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OPTIONS请求
|
|
|
+ */
|
|
|
+ public String doOptions(String url) {
|
|
|
+ return doOptions(url, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OPTIONS请求(带请求头)
|
|
|
+ */
|
|
|
+ public String doOptions(String url, HttpHeaders headers) {
|
|
|
+ return execute(Method.OPTIONS, url, null, null, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 通用请求方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用请求方法(完整参数)
|
|
|
+ *
|
|
|
+ * @param method 请求方式
|
|
|
+ * @param url 请求地址
|
|
|
+ * @param params URL查询参数
|
|
|
+ * @param body 请求体(JSON)
|
|
|
+ * @param headers 请求头
|
|
|
+ * @return 响应体字符串
|
|
|
+ */
|
|
|
+ public String doRequest(Method method, String url, Map<String, Object> params,
|
|
|
+ String body, HttpHeaders headers) {
|
|
|
+ return execute(method, url, params, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 响应对象方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * GET请求(返回HttpResponse对象,可获取状态码、响应头等)
|
|
|
+ */
|
|
|
+ public HttpResponse doGetForResponse(String url, Map<String, Object> params, HttpHeaders headers) {
|
|
|
+ return executeForResponse(Method.GET, url, params, null, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST请求(返回HttpResponse对象,可获取状态码、响应头等)
|
|
|
+ */
|
|
|
+ public HttpResponse doPostForResponse(String url, String body, HttpHeaders headers) {
|
|
|
+ return executeForResponse(Method.POST, url, null, body, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * POST表单请求(返回HttpResponse对象)
|
|
|
+ */
|
|
|
+ public HttpResponse doPostFormForResponse(String url, Map<String, Object> formParams, HttpHeaders headers) {
|
|
|
+ return executeFormForResponse(Method.POST, url, formParams, headers);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 内部执行方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行HTTP请求(JSON体)
|
|
|
+ */
|
|
|
+ private String execute(Method method, String url, Map<String, Object> params,
|
|
|
+ String body, HttpHeaders headers) {
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ HttpRequest request = buildRequest(method, url, params, body, headers);
|
|
|
+ HttpResponse response = request.timeout(DEFAULT_TIMEOUT).execute();
|
|
|
+ // 使用bodyBytes()避免Hutool根据Content-Type自动解析响应体
|
|
|
+ byte[] bodyBytes = response.bodyBytes();
|
|
|
+ String result = bodyBytes != null ? new String(bodyBytes, StandardCharsets.UTF_8) : null;
|
|
|
+ log.info("\n----------------------> HTTP请求成功: \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> body:{},\n----------------------> 耗时:{}ms, \n----------------------> 状态码:{}, \n----------------------> 响应长度:{}",
|
|
|
+ method, url, TextUtils.isEmpty(body) ? null : DaDiAESUtil.decryptStr(body), System.currentTimeMillis() - startTime, response.getStatus(),
|
|
|
+ result != null ? result.length() : 0);
|
|
|
+ return result;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("\n----------------------> HTTP请求失败, \n----------------------> method:{}, \n----------------------> url:{},\n----------------------> 耗时:{}ms",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, e);
|
|
|
+ throw new RuntimeException(StrUtil.format("\n----------------------> HTTP请求失败: {}, {}", method, url), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行HTTP请求(表单体)
|
|
|
+ */
|
|
|
+ private String executeForm(Method method, String url, Map<String, Object> formParams,
|
|
|
+ HttpHeaders headers) {
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ HttpRequest request = createRequest(method, url);
|
|
|
+ setCommonFormHeaders(request);
|
|
|
+ setHeaders(request, headers);
|
|
|
+ if (formParams != null && !formParams.isEmpty()) {
|
|
|
+ request.form(formParams);
|
|
|
+ }
|
|
|
+ HttpResponse response = request.timeout(DEFAULT_TIMEOUT).execute();
|
|
|
+ // 使用bodyBytes()避免Hutool根据Content-Type自动解析响应体
|
|
|
+ byte[] bodyBytes = response.bodyBytes();
|
|
|
+ String result = bodyBytes != null ? new String(bodyBytes, StandardCharsets.UTF_8) : null;
|
|
|
+ log.info("\n----------------------> HTTP表单请求成功, \n----------------------> method:{},\n----------------------> url:{},\n----------------------> 耗时:{}ms, \n----------------------> 状态码:{}, \n----------------------> 响应长度:{}",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, response.getStatus(),
|
|
|
+ result != null ? result.length() : 0);
|
|
|
+ return result;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("HTTP表单请求失败, \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> 耗时:{}ms",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, e);
|
|
|
+ throw new RuntimeException(StrUtil.format("HTTP表单请求失败: {}, {}", method, url), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行HTTP请求(返回完整响应对象)
|
|
|
+ */
|
|
|
+ private HttpResponse executeForResponse(Method method, String url, Map<String, Object> params,
|
|
|
+ String body, HttpHeaders headers) {
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ HttpRequest request = buildRequest(method, url, params, body, headers);
|
|
|
+ HttpResponse response = request.timeout(DEFAULT_TIMEOUT).execute();
|
|
|
+ log.info("\n----------------------> HTTP请求成功, \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> body:{},\n----------------------> 耗时:{}ms, \n----------------------> 状态码:{}",
|
|
|
+ method, url, TextUtils.isEmpty(body) ? null : DaDiAESUtil.decryptStr(body), System.currentTimeMillis() - startTime, response.getStatus());
|
|
|
+ return response;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("\n----------------------> HTTP请求失败, \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> 耗时:{}ms",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, e);
|
|
|
+ throw new RuntimeException(StrUtil.format("\n----------------------> HTTP请求失败: {}, {}", method, url), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行HTTP表单请求(返回完整响应对象)
|
|
|
+ */
|
|
|
+ private HttpResponse executeFormForResponse(Method method, String url, Map<String, Object> formParams,
|
|
|
+ HttpHeaders headers) {
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ HttpRequest request = createRequest(method, url);
|
|
|
+ setCommonFormHeaders(request);
|
|
|
+ setHeaders(request, headers);
|
|
|
+ if (formParams != null && !formParams.isEmpty()) {
|
|
|
+ request.form(formParams);
|
|
|
+ }
|
|
|
+ HttpResponse response = request.timeout(DEFAULT_TIMEOUT).execute();
|
|
|
+ log.info("HTTP表单请求成功, \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> 耗时:{}ms, \n----------------------> 状态码:{}",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, response.getStatus());
|
|
|
+ return response;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("HTTP表单请求失败, \n----------------------> method:{}, \n----------------------> url:{}, \n----------------------> 耗时:{}ms",
|
|
|
+ method, url, System.currentTimeMillis() - startTime, e);
|
|
|
+ throw new RuntimeException(StrUtil.format("HTTP表单请求失败: {}, {}", method, url), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建HttpRequest对象(JSON体)
|
|
|
+ */
|
|
|
+ private HttpRequest buildRequest(Method method, String url, Map<String, Object> params,
|
|
|
+ String body, HttpHeaders headers) {
|
|
|
+ HttpRequest request = createRequest(method, url);
|
|
|
+ setCommonHeaders(request);
|
|
|
+ setHeaders(request, headers);
|
|
|
+ setParams(request, params);
|
|
|
+ setBody(request, body);
|
|
|
+ return request;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置公共请求头(Token + 固定头)
|
|
|
+ */
|
|
|
+ private void setCommonHeaders(HttpRequest request) {
|
|
|
+ COMMON_HEADERS.forEach(request::header);
|
|
|
+ request.header("Content-Type", "application/json; charset=utf-8");
|
|
|
+ if (getToken() != null && !getToken().isEmpty()) {
|
|
|
+ request.header("X-Access-Token", getToken());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置Form请求的公共请求头(不含Content-Type,由request.form()自动设置)
|
|
|
+ */
|
|
|
+ private void setCommonFormHeaders(HttpRequest request) {
|
|
|
+ COMMON_HEADERS.forEach(request::header);
|
|
|
+ if (getToken() != null && !getToken().isEmpty()) {
|
|
|
+ request.header("X-Access-Token", getToken());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建基础请求对象
|
|
|
+ */
|
|
|
+ private HttpRequest createRequest(Method method, String url) {
|
|
|
+ return switch (method) {
|
|
|
+ case GET -> HttpRequest.get(url);
|
|
|
+ case POST -> HttpRequest.post(url);
|
|
|
+ case PUT -> HttpRequest.put(url);
|
|
|
+ case DELETE -> HttpRequest.delete(url);
|
|
|
+ case PATCH -> HttpRequest.patch(url);
|
|
|
+ case HEAD -> HttpRequest.head(url);
|
|
|
+ case OPTIONS -> HttpRequest.options(url);
|
|
|
+ case TRACE -> HttpRequest.trace(url);
|
|
|
+ default -> throw new IllegalStateException("Unexpected value: " + method);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置参数
|
|
|
+ */
|
|
|
+ private void setParams(HttpRequest request, Map<String, Object> params) {
|
|
|
+ if (params != null && !params.isEmpty()) {
|
|
|
+ request.form(params);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置请求体
|
|
|
+ */
|
|
|
+ private void setBody(HttpRequest request, String body) {
|
|
|
+ if (StrUtil.isNotBlank(body)) {
|
|
|
+ request.body(body);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置请求头(HttpHeaders → 取每个header的第一个值)
|
|
|
+ */
|
|
|
+ private void setHeaders(HttpRequest request, HttpHeaders headers) {
|
|
|
+ if (headers != null && !headers.isEmpty()) {
|
|
|
+ headers.forEach((key, values) -> {
|
|
|
+ if (values != null && !values.isEmpty()) {
|
|
|
+ request.header(key, values.get(0));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|