package com.xly.util; import okhttp3.*; import okio.Buffer; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.TimeUnit; /** * OkHttp3通用工具类 * 支持GET/POST/PUT/DELETE请求,同步/异步调用,文件上传/下载等 */ public class OkHttpUtil { private static volatile OkHttpUtil instance; private OkHttpClient client; // 默认配置 private static final long CONNECT_TIMEOUT = 10; private static final long READ_TIMEOUT = 30; private static final long WRITE_TIMEOUT = 30; private OkHttpUtil() { initClient(); } private OkHttpUtil(long connectTimeout, long readTimeout, long writeTimeout) { initClient(connectTimeout, readTimeout, writeTimeout); } /** * 获取单例实例(默认配置) */ public static OkHttpUtil getInstance() { if (instance == null) { synchronized (OkHttpUtil.class) { if (instance == null) { instance = new OkHttpUtil(); } } } return instance; } /** * 获取自定义配置的单例 */ public static OkHttpUtil getInstance(long connectTimeout, long readTimeout, long writeTimeout) { return new OkHttpUtil(connectTimeout, readTimeout, writeTimeout); } /** * 初始化默认客户端 */ private void initClient() { initClient(CONNECT_TIMEOUT, READ_TIMEOUT, WRITE_TIMEOUT); } /** * 初始化自定义客户端 */ private void initClient(long connectTimeout, long readTimeout, long writeTimeout) { client = new OkHttpClient.Builder() .connectTimeout(connectTimeout, TimeUnit.SECONDS) .readTimeout(readTimeout, TimeUnit.SECONDS) .writeTimeout(writeTimeout, TimeUnit.SECONDS) .addInterceptor(new LoggingInterceptor()) .build(); } /** * 更新客户端配置 */ public void updateClient(OkHttpClient.Builder builder) { client = builder.build(); } // ==================== 同步请求方法 ==================== /** * 同步GET请求 */ public String get(String url) throws IOException { return get(url, null, null); } public String get(String url, Map headers) throws IOException { return get(url, headers, null); } public String get(String url, Map headers, Map params) throws IOException { Request request = buildRequest(url, "GET", headers, params, null); return executeRequest(request); } /** * 同步POST请求 - JSON */ public String postJson(String url, String json) throws IOException { return postJson(url, null, json); } public String postJson(String url, Map headers, String json) throws IOException { RequestBody body = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8")); Request request = buildRequest(url, "POST", headers, null, body); return executeRequest(request); } /** * 同步POST请求 - Form表单 */ public String postForm(String url, Map formParams) throws IOException { return postForm(url, null, formParams); } public String postForm(String url, Map headers, Map formParams) throws IOException { FormBody.Builder builder = new FormBody.Builder(); if (formParams != null) { for (Map.Entry entry : formParams.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } } Request request = buildRequest(url, "POST", headers, null, builder.build()); return executeRequest(request); } /** * 同步POST请求 - 多部分表单(文件上传) */ public String uploadFile(String url, Map headers, Map formParams, Map files) throws IOException { MultipartBody.Builder builder = new MultipartBody.Builder() .setType(MultipartBody.FORM); // 添加普通表单参数 if (formParams != null) { for (Map.Entry entry : formParams.entrySet()) { builder.addFormDataPart(entry.getKey(), entry.getValue()); } } // 添加文件 if (files != null) { for (Map.Entry entry : files.entrySet()) { File file = entry.getValue(); if (file.exists()) { RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/octet-stream")); builder.addFormDataPart(entry.getKey(), file.getName(), fileBody); } } } Request request = buildRequest(url, "POST", headers, null, builder.build()); return executeRequest(request); } /** * 同步PUT请求 */ public String putJson(String url, String json) throws IOException { return putJson(url, null, json); } public String putJson(String url, Map headers, String json) throws IOException { RequestBody body = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8")); Request request = buildRequest(url, "PUT", headers, null, body); return executeRequest(request); } /** * 同步DELETE请求 */ public String delete(String url) throws IOException { return delete(url, null); } public String delete(String url, Map headers) throws IOException { Request request = buildRequest(url, "DELETE", headers, null, null); return executeRequest(request); } // ==================== 异步请求方法 ==================== /** * 异步GET请求 */ public void getAsync(String url, Callback callback) { getAsync(url, null, null, callback); } public void getAsync(String url, Map headers, Map params, Callback callback) { Request request = buildRequest(url, "GET", headers, params, null); executeAsync(request, callback); } /** * 异步POST请求 - JSON */ public void postJsonAsync(String url, String json, Callback callback) { postJsonAsync(url, null, json, callback); } public void postJsonAsync(String url, Map headers, String json, Callback callback) { RequestBody body = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8")); Request request = buildRequest(url, "POST", headers, null, body); executeAsync(request, callback); } // ==================== 通用构建方法 ==================== /** * 构建请求 */ private Request buildRequest(String url, String method, Map headers, Map params, RequestBody body) { // 处理URL参数 HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder(); if (params != null && !params.isEmpty()) { for (Map.Entry entry : params.entrySet()) { urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); } } // 构建请求 Request.Builder requestBuilder = new Request.Builder() .url(urlBuilder.build()); // 添加请求头 if (headers != null && !headers.isEmpty()) { for (Map.Entry entry : headers.entrySet()) { requestBuilder.addHeader(entry.getKey(), entry.getValue()); } } // 设置请求方法和请求体 switch (method.toUpperCase()) { case "GET": requestBuilder.get(); break; case "POST": if (body != null) { requestBuilder.post(body); } else { requestBuilder.post(RequestBody.create("", null)); } break; case "PUT": requestBuilder.put(body != null ? body : RequestBody.create("", null)); break; case "DELETE": requestBuilder.delete(body != null ? body : RequestBody.create("", null)); break; default: throw new IllegalArgumentException("Unsupported HTTP method: " + method); } return requestBuilder.build(); } /** * 执行同步请求 */ private String executeRequest(Request request) throws IOException { try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("Unexpected code: " + response.code() + ", message: " + response.message()); } ResponseBody body = response.body(); return body != null ? body.string() : ""; } } /** * 执行异步请求 */ private void executeAsync(Request request, Callback callback) { client.newCall(request).enqueue(callback != null ? callback : new DefaultCallback()); } // ==================== 工具方法 ==================== /** * 将字符串数组转换为Header Map * 格式: ["key1", "value1", "key2", "value2", ...] */ public static Map arrayToHeaderMap(String[] headerArray) { Map headers = new HashMap<>(); if (headerArray == null || headerArray.length % 2 != 0) { return headers; } for (int i = 0; i < headerArray.length; i += 2) { if (i + 1 < headerArray.length) { headers.put(headerArray[i], headerArray[i + 1]); } } return headers; } /** * 将字符串数组转换为参数Map */ public static Map arrayToParamMap(String[] paramArray) { return arrayToHeaderMap(paramArray); // 逻辑相同 } /** * 构建URL参数字符串 */ public static String buildQueryString(Map params) { if (params == null || params.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); for (Map.Entry entry : params.entrySet()) { if (sb.length() > 0) { sb.append("&"); } sb.append(entry.getKey()) .append("=") .append(entry.getValue()); } return sb.toString(); } /** * 下载文件 */ public boolean downloadFile(String url, String savePath) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { ResponseBody body = response.body(); if (body != null) { File file = new File(savePath); // 这里可以添加文件写入逻辑 // 或者使用body.byteStream()处理大文件 return true; } } return false; } } // ==================== 内部类 ==================== /** * 默认回调 */ private static class DefaultCallback implements Callback { @Override public void onFailure(Call call, IOException e) { System.err.println("Request failed: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String responseData = response.body().string(); System.out.println("Response: " + responseData); } else { System.err.println("Request failed with code: " + response.code()); } } } /** * 日志拦截器 */ private static class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long startTime = System.nanoTime(); System.out.println(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); // 打印请求体(如果是可读的) if (request.body() != null) { Buffer buffer = new Buffer(); request.body().writeTo(buffer); System.out.println("Request Body: " + buffer.readString(StandardCharsets.UTF_8)); } Response response = chain.proceed(request); long endTime = System.nanoTime(); System.out.println(String.format("Received response for %s in %.1fms%n%s", response.request().url(), (endTime - startTime) / 1e6d, response.headers())); return response; } } // ==================== Getter/Setter ==================== public OkHttpClient getClient() { return client; } public void setClient(OkHttpClient client) { this.client = client; } public static void main(String[] args) { // 1. 获取实例 OkHttpUtil httpUtil = OkHttpUtil.getInstance(); // 2. 同步GET请求 try { // 普通GET String result = httpUtil.get("https://api.example.com/data"); System.out.println(result); // 带参数的GET Map params = new HashMap<>(); params.put("page", "1"); params.put("size", "10"); String result2 = httpUtil.get("https://api.example.com/data", null, params); // 带Header的GET String[] headersArray = {"Authorization", "Bearer token123", "Accept", "application/json"}; Map headers = OkHttpUtil.arrayToHeaderMap(headersArray); String result3 = httpUtil.get("https://api.example.com/data", headers, params); } catch (IOException e) { e.printStackTrace(); } // 3. 同步POST请求 try { // JSON POST String json = "{\"name\":\"张三\",\"age\":25}"; String result = httpUtil.postJson("https://api.example.com/user", json); // Form POST Map formParams = new HashMap<>(); formParams.put("username", "admin"); formParams.put("password", "123456"); String result2 = httpUtil.postForm("https://api.example.com/login", formParams); } catch (IOException e) { e.printStackTrace(); } // 4. 异步请求 httpUtil.getAsync("https://api.example.com/data", new Callback() { @Override public void onFailure(Call call, IOException e) { System.err.println("Request failed: " + e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String responseData = response.body().string(); System.out.println("Async response: " + responseData); } } }); // 5. 文件上传 try { Map formParams = new HashMap<>(); formParams.put("description", "test file"); Map files = new HashMap<>(); files.put("file", new File("/path/to/file.txt")); String result = httpUtil.uploadFile( "https://api.example.com/upload", null, formParams, files ); } catch (IOException e) { e.printStackTrace(); } } }