OkHttpClientUtils
import com.jd.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSource;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@Slf4j
public class OkHttpClientUtils {
private static volatile OkHttpClientUtils mInstance;
private OkHttpClient client;
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=UTF-8");
private OkHttpClientUtils(OkHttpClient okHttpClient) {
this.client = okHttpClient;
}
private static OkHttpClient obtainDefaultOkHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(new LogInterceptor())
.retryOnConnectionFailure(true)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.build();
}
public static OkHttpClientUtils getInstance(){
return getInstance(null);
}
public static OkHttpClientUtils getInstance(OkHttpClient mOkHttpClient) {
if (mInstance == null) {
synchronized (OkHttpClientUtils.class) {
if (mInstance == null) {
mInstance = Optional.ofNullable(mOkHttpClient).map(OkHttpClientUtils::new).orElseGet(() -> {
return new OkHttpClientUtils(obtainDefaultOkHttpClient());
});
}
}
}
return mInstance;
}
public Response doGet(String url, Map<String, String> headers) {
log.info("HttpClientUtil doGet url: {}", url);
Request request = new Request.Builder()
.url(url)
.get()
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http get method execute error", e);
}
return response;
}
public Response doGet(String url, Map<String, Object> params, Map<String, String> headers) {
if (CollectionUtils.isEmpty(params)) {
return doGet(url, headers);
}
String urlWithParams = UriUtil.generateUrlWithParams(url, params);
return doGet(urlWithParams, headers);
}
public Response doPost(String url, String paramJson, Map<String, String> headers) {
RequestBody body = RequestBody.create(paramJson, MEDIA_TYPE_JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http post method execute error", e);
}
return response;
}
public Response doPostByForm(String url, Map<String, String> formData, Map<String, String> headers) {
log.info("HttpClientUtil doPost url: {} formData: {}", url, formData);
FormBody.Builder builder = new FormBody.Builder();
if (!CollectionUtils.isEmpty(formData)) {
formData.forEach(builder::add);
}
FormBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http post method execute error", e);
}
return response;
}
public Response doPut(String url, String paramJson, Map<String, String> headers) {
log.info("HttpClientUtil doPut url: {} body: {}", url, paramJson);
RequestBody body = RequestBody.create(paramJson, MEDIA_TYPE_JSON);
Request request = new Request.Builder()
.url(url)
.put(body)
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http put method execute error", e);
}
return response;
}
public Response doDelete(String url, String string, Map<String, String> headers) {
log.info("HttpClientUtil doDelete url: {} body: {}", url, string);
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, string);
Request request = new Request.Builder()
.url(url)
.delete(body)
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http delete method execute error", e);
}
return response;
}
public Response doDelete(String url, Map<String, String> headers) {
log.info("HttpClientUtil doDelete url: {}", url);
Request request = new Request.Builder()
.url(url)
.delete()
.headers(buildHeaders(headers))
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
log.error("http delete method execute error", e);
}
return response;
}
private static Headers buildHeaders(Map<String, String> headers) {
Headers.Builder builder = new Headers.Builder();
if (Objects.isNull(headers) || headers.isEmpty()) {
return builder.build();
}
headers.forEach(builder::add);
return builder.build();
}
public static String requestBodyToString(final RequestBody request) {
try {
final Buffer buffer = new Buffer();
if (request != null) {
request.writeTo(buffer);
} else {
return "";
}
return buffer.readUtf8();
} catch (final IOException e) {
return "";
}
}
private static String getTraceId(final Headers headers) {
for (int i = 0, count = headers.size(); i < count; i++) {
if ("TRACE-ID".equals(headers.name(i).toUpperCase())) {
return headers.value(i);
}
}
return "";
}
public static String getBodyString(final Response response) {
if (Objects.isNull(response)) {
log.error("http response body is null");
return null;
}
if (Objects.nonNull(response.body())) {
try {
BufferedSource source = response.body().source();
source.request(Long.MAX_VALUE);
Buffer buffer = source.buffer();
return buffer.clone().readString(StandardCharsets.UTF_8);
} catch (IOException e) {
log.error("http response body string error", e);
return null;
}
}
return null;
}
private static class LogInterceptor implements Interceptor {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();
RequestBody body = request.body();
String requestBodyString = requestBodyToString(body);
Response response = null;
try {
response = chain.proceed(request);
} catch (IOException e) {
log.error("[okhttp time out] 请求 {}{} 超时", url.host(), url.encodedPath());
throw e;
}
log.info(String.format("url: %s%s requestBodyString: %s response: %s", url.host(), url.encodedPath(), requestBodyString, JSON.toJSONString(response)));
return response;
}
}
public static class RetryInterceptor implements Interceptor {
private final int maxRetryCount;
public RetryInterceptor(int maxRetryCount) {
this.maxRetryCount = maxRetryCount;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
int retryCount = 0;
while (retryCount < maxRetryCount) {
try {
return chain.proceed(request);
} catch (IOException e) {
if (++retryCount == maxRetryCount) {
throw e;
}
}
}
throw new IOException("Max retry count reached");
}
}
}
UriUtil
import org.apache.commons.lang.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;
public class UriUtil {
public static String generateUrlWithParams(String url, Map<String, Object> params) {
StringBuilder resUrl = new StringBuilder(url);
int i = 0;
for (String key : params.keySet()) {
if (Objects.isNull(params.get(key)) || StringUtils.isEmpty(params.get(key).toString())) {
continue;
}
if (url.indexOf('?') != -1) {
resUrl.append("&");
} else {
if (i == 0) {
resUrl.append("?");
} else {
resUrl.append("&");
}
}
Object param = params.get(key);
try {
param = URLEncoder.encode(param.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
}
resUrl.append(key).append("=").append(param);
i++;
}
return resUrl.toString();
}
}