176 lines
6.3 KiB
Java
176 lines
6.3 KiB
Java
package com.knowledge.base.infrastructure.util;
|
||
|
||
import com.fasterxml.jackson.core.type.TypeReference;
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import okhttp3.*;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import java.io.IOException;
|
||
import java.util.Map;
|
||
import java.util.concurrent.TimeUnit;
|
||
|
||
/**
|
||
* OkHttp封装的 HTTP 客户端工具类(支持 JSON POST、GET、Token注入、泛型反序列化、流式请求)
|
||
*/
|
||
@Slf4j
|
||
@Component
|
||
public class HttpHelper {
|
||
|
||
private final OkHttpClient client;
|
||
private final ObjectMapper objectMapper;
|
||
|
||
public HttpHelper() {
|
||
this.client = new OkHttpClient.Builder()
|
||
.connectTimeout(60, TimeUnit.SECONDS)
|
||
.readTimeout(300, TimeUnit.SECONDS)
|
||
.build();
|
||
this.objectMapper = new ObjectMapper();
|
||
}
|
||
|
||
/**
|
||
* 发送 POST JSON 请求,自动反序列化为 Map
|
||
*/
|
||
public Map<String, Object> postJson(String url, Map<String, Object> body, String token) throws IOException {
|
||
Request request = buildJsonRequest(url, body, token, "POST");
|
||
return executeJson(request);
|
||
}
|
||
|
||
/**
|
||
* 发送 GET 请求,自动反序列化为 Map
|
||
*/
|
||
public Map<String, Object> get(String url, String token) throws IOException {
|
||
Request request = buildJsonRequest(url, null, token, "GET");
|
||
return executeJson(request);
|
||
}
|
||
|
||
/**
|
||
* 流式 POST 请求,返回 Response 实例,调用方负责关闭 response.body().close()
|
||
*/
|
||
public Response postStream(String url, Map<String, Object> body, String token) throws IOException {
|
||
String json = objectMapper.writeValueAsString(body);
|
||
RequestBody requestBody = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
|
||
|
||
Request request = new Request.Builder()
|
||
.url(url)
|
||
.addHeader("Authorization", token)
|
||
.addHeader("Accept", "text/event-stream")
|
||
.addHeader("Connection", "keep-alive")
|
||
.post(requestBody)
|
||
.build();
|
||
|
||
return client.newCall(request).execute();
|
||
}
|
||
|
||
/**
|
||
* 构建 JSON 类型的 Request 请求
|
||
*/
|
||
private Request buildJsonRequest(String url, Map<String, Object> body, String token, String method) throws IOException {
|
||
RequestBody requestBody = null;
|
||
if (body != null) {
|
||
String json = objectMapper.writeValueAsString(body);
|
||
requestBody = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
|
||
}
|
||
|
||
Request.Builder builder = new Request.Builder().url(url);
|
||
if (token != null && !token.isBlank()) {
|
||
builder.header("Authorization", "Bearer " + token);
|
||
}
|
||
|
||
switch (method.toUpperCase()) {
|
||
case "POST":
|
||
builder.post(requestBody != null ? requestBody : RequestBody.create(new byte[0]));
|
||
break;
|
||
case "GET":
|
||
builder.get();
|
||
break;
|
||
case "PUT":
|
||
builder.put(requestBody);
|
||
break;
|
||
case "DELETE":
|
||
if (requestBody != null) {
|
||
builder.delete(requestBody);
|
||
} else {
|
||
builder.delete();
|
||
}
|
||
break;
|
||
default:
|
||
throw new IllegalArgumentException("不支持的请求方法:" + method);
|
||
}
|
||
|
||
return builder.build();
|
||
}
|
||
|
||
/**
|
||
* 通用 HTTP 请求方法,支持任意 method、headers、请求体,自动反序列化返回
|
||
*
|
||
* @param url 请求地址
|
||
* @param method 请求方法,如 GET、POST、PUT、DELETE
|
||
* @param headers 请求头(可选,可为 null)
|
||
* @param body 请求体对象(可选,可为 null)
|
||
* @param responseType 返回类型(例如 Map.class)
|
||
* @param <T> 泛型类型
|
||
* @return 反序列化后的对象
|
||
* @throws IOException 请求失败或 JSON 解析异常
|
||
*/
|
||
/**
|
||
* 通用 HTTP 请求方法,支持任意 method、headers、请求体,支持泛型 TypeReference<T> 返回(Jackson)
|
||
*/
|
||
public <T> T exchange(String url, String method, Map<String, String> headers, Object body, TypeReference<T> typeRef) throws IOException {
|
||
RequestBody requestBody = null;
|
||
if (body != null) {
|
||
String json = objectMapper.writeValueAsString(body);
|
||
requestBody = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
|
||
}
|
||
|
||
Request.Builder builder = new Request.Builder().url(url);
|
||
|
||
if (headers != null) {
|
||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||
builder.addHeader(entry.getKey(), entry.getValue());
|
||
}
|
||
}
|
||
|
||
switch (method.toUpperCase()) {
|
||
case "POST":
|
||
builder.post(requestBody != null ? requestBody : RequestBody.create(new byte[0]));
|
||
break;
|
||
case "PUT":
|
||
builder.put(requestBody != null ? requestBody : RequestBody.create(new byte[0]));
|
||
break;
|
||
case "DELETE":
|
||
builder.delete(requestBody != null ? requestBody : null);
|
||
break;
|
||
case "GET":
|
||
default:
|
||
builder.get();
|
||
break;
|
||
}
|
||
|
||
Request request = builder.build();
|
||
|
||
try (Response response = client.newCall(request).execute()) {
|
||
if (!response.isSuccessful()) {
|
||
throw new IOException("请求失败: " + response.code() + " - " + response.message());
|
||
}
|
||
String json = response.body().string();
|
||
return objectMapper.readValue(json, typeRef);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 执行请求并解析为 Map
|
||
*/
|
||
private Map<String, Object> executeJson(Request request) throws IOException {
|
||
try (Response response = client.newCall(request).execute()) {
|
||
if (!response.isSuccessful()) {
|
||
throw new IOException("请求失败: " + response.code() + " - " + response.message());
|
||
}
|
||
String json = response.body().string();
|
||
return objectMapper.readValue(json, new TypeReference<>() {});
|
||
}
|
||
}
|
||
}
|