請求三方接口工具封裝
實現邏輯:
- 發起請求,輸入基本請求信息:請求地址,請求類型,請求參數,是否需要認證
- 工具自動為需要添加認證的請求添加認證,如果發現token快要過期或返回的錯誤編碼為定義的認證失敗code,則自動重新獲取token重新請求
package com.xxx;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import lombok.Data;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;/*** GeneralRequest* 通用請求** @author cd* @date 2024/12/18 10:51*/
@Data
public class GeneralRequest {/*** 請求路徑*/private String url;/*** 方法類型*/private Method method;/*** 請求頭*/private Map<String, String> headers;/*** form表單類型參數*/private Map<String, Object> form;/*** 請求體body*/private String body;/*** 是否需要鑒權*/private Boolean needAuth;/*** http請求工具*/private HttpRequest httpRequest;public GeneralRequest(String url, Method method, Boolean needAuth) {this.url = url;this.method = method;this.form = new HashMap<>();this.headers = new HashMap<>();this.needAuth = Objects.equals(needAuth, true);this.httpRequest = HttpRequest.of(url).method(method);}public GeneralRequest body(String body) {this.body = body;this.httpRequest.body(body);return this;}public GeneralRequest form(Map<String, Object> form) {this.form = form;this.httpRequest.form(form);return this;}public GeneralRequest addHeader(String name, String value) {this.headers.put(name, value);this.httpRequest.header(name, value);return this;}public String getParameter() {if (StrUtil.isNotBlank(this.body)) {return this.body;}if (CollUtil.isNotEmpty(this.form)) {return JSON.toJSONString(this.form);}return "";}
}
package com.xxx;import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;import java.time.LocalDateTime;
import java.util.Map;/*** XxxHttpUtil** @author cd* @date 2024/12/18 13:46*/
@Slf4j
public class XxxHttpUtil {private TokenResponse cacheTokenResponse = null;/*** 獲取token** @param refreshToken 刷新token* @return*/public TokenResponse getToken(boolean refreshToken) {TokenResponse tokenResponse = null;if (!refreshToken) {tokenResponse = this.cacheTokenResponse;}if (tokenResponse != null) {return tokenResponse;}// 模擬重新獲取tokenBaseRes<TokenResponse> baseRes = executeFrom("http://localhost:8080/getToken", Method.GET, false, null, new TypeReference<>() {});tokenResponse = baseRes.getData();this.cacheTokenResponse = tokenResponse;return tokenResponse;}public String signRequest(GeneralRequest generalRequest, boolean refreshToken) {TokenResponse tokenResponse = null;if (generalRequest.getNeedAuth()) {tokenResponse = getToken(refreshToken);
// 判斷token是否快過期if (LocalDateTime.now().plusSeconds(10).isAfter(tokenResponse.getExpiresTime())) {tokenResponse = getToken(true);}
// 添加認證請求頭generalRequest.addHeader("Authorization", tokenResponse.getAccessToken());}HttpResponse httpResponse = generalRequest.getHttpRequest().execute();int httpResponseStatus = httpResponse.getStatus();boolean success = httpResponseStatus == HttpStatus.HTTP_OK;String result = null;if (success) {result = httpResponse.body();}log.info("接口調用記錄,HttpStatusCode:{},請求是否成功:{},請求地址:{},參數:{},結果:{}",httpResponseStatus, success ? "成功" : "失敗", generalRequest.getUrl(), generalRequest.getParameter(), result);return result;}public <R> R doAction(GeneralRequest generalRequest, TypeReference<R> type) {String result = signRequest(generalRequest, false);
// 按三方返回格式判斷,一般返回有code、success、dataif (StrUtil.contains(result, "code")) {JSONObject jsonObject = JSON.parseObject(result);String code = jsonObject.getString("code");
// 200:成功if (StrUtil.equals(code, "200")) {return JSON.parseObject(result, type);}
// 200:鑒權失敗
// 刷新token重試else if (StrUtil.equals(code, "500")) {result = signRequest(generalRequest, true);if (StrUtil.isNotBlank(result)) {return JSON.parseObject(result, type);}} else {return JSON.parseObject(result, type);}}return null;}public <R> R execute(String url, Method method, Boolean needAuth, String body, Map<String, Object> formParams, TypeReference<R> type) {GeneralRequest generalRequest = new GeneralRequest(url, method, needAuth);if (body != null) {generalRequest.body(body);}if (formParams != null) {generalRequest.form(formParams);}return doAction(generalRequest, type);}public <R> R executeJson(String url, Method method, String body, TypeReference<R> type) {return this.execute(url, method, true, body, null, type);}public <R> R executeJson(String url, Method method, Boolean needAuth, String body, TypeReference<R> type) {return this.execute(url, method, needAuth, body, null, type);}public <R> R executeFrom(String url, Method method, Boolean needAuth, Map<String, Object> formParams, TypeReference<R> type) {return this.execute(url, method, needAuth, null, formParams, type);}public <R> R executeFrom(String url, Method method, Map<String, Object> formParams, TypeReference<R> type) {return this.execute(url, method, true, null, formParams, type);}
}
package com.xxx;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;/*** TokenResponse** @author cd* @date 2024/12/18 13:50*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TokenResponse {/*** token*/private String accessToken;/*** 過期時間*/private LocalDateTime expiresTime;
}