# SpringBoot使用Okhttp3
记录下 Okhttp3
# 1. 简单使用
API 简单使用
# 1.1. Closed
// 下面的代码会触发关闭响应体,下次就无法再调用获取请求结果了
Response.close();
Response.body().close();
Response.body().source().close();
Response.body().charStream().close();
Response.body().byteString().close();
Response.body().bytes();
Response.body().string();
// 使用下面的方式解决,相当于复制,上面的代码还能继续使用
ResponseBody responseBody = response.peekBody(Long.MAX_VALUE);
# 1.2. Retry
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.io.IOException;
/**
* 请求重试拦截器
*
* @author wliduo[i@dolyw.com]
* @date 2020/5/13 10:52
*/
@Slf4j
public class CustomRetryInterceptor implements Interceptor {
/**
* 默认最大重试次数
*/
public int maxRetry = 3;
public CustomRetryInterceptor() {}
public CustomRetryInterceptor(int maxRetry) {
this.maxRetry = maxRetry;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
for (int i = 1; i < maxRetry; i++) {
// 响应成功且内容也是成功的才不进行重试,必须使用peekBody()获取ResponseBody,
// 这样外部还能再获取ResponseBody
ResponseBody responseBody = response.peekBody(Long.MAX_VALUE);
String result = responseBody.string();
if (response.isSuccessful()) {
CommonResp commonResp = JSON.parseObject(result, CommonResp.class);
int status = commonResp.getStatus();
// 响应码为200到300之前才算成功
if (status >= CommonResp.OK && status < CommonResp.MULTIPLE_CHOICES) {
break;
}
}
// 请求异常开始重试
log.debug("重试第{}次,请求地址:{},上次请求结果:{},", i, request.url(), result);
// 发起重试请求
response = chain.proceed(request);
}
return response;
}
}
# 1.3. Get
/**
* 回调签名验证
*
* @param sign
* @return java.lang.Boolean
* @throws
* @author wliduo[i@dolyw.com]
* @date 2020/5/13 18:42
*/
public Boolean saaVerify(String sign) {
// 开始发起请求
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
// 请求地址,请求头和参数
String url = verifyUrl + "?sign=" + sign;
Request request = new Request.Builder().url(url).get().build();
// 返回结果
String result = "";
// 发起请求
try (Response response = okHttpClient.newCall(request).execute()) {
// 获取结果
result = response.body().string();
log.info("请求地址:{},请求结果:{}", url,result);
return Boolean.parseBoolean(result);
} catch (SocketTimeoutException e) {
log.error("签名验证请求超时异常,请求地址:{}", url);
return false;
} catch (Exception e) {
log.error("签名验证失败出现异常,请求结果:{},错误信息: {}", result, ExceptionUtil.getExceptionMessage(e));
return false;
}
}
# 1.4. Post
Post 几种类型
text/plain
/**
* 获取Token
*
* @param
* @return java.lang.String
* @throws
* @author wliduo[i@dolyw.com]
* @date 2020/5/13 19:20
*/
public String getToken() {
String token = redisTemplate.opsForValue().get("XXX:XXX:Token");
if (StringUtils.isNotEmpty(token)) {
return token;
}
// 开始发起请求
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
// 请求地址,请求头和参数
String url = caaBaseUrl + getToken;
String content = "grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret;
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), content);
Request request = new Request.Builder().url(url).post(requestBody).build();
// 返回结果
String result = "";
// 发起请求
try (Response response = okHttpClient.newCall(request).execute()) {
// 获取结果
result = response.body().string();
log.info("请求地址:{},请求结果:{}", url, result);
XXXToken xxxToken = JSON.parseObject(result, XXXToken.class);
token = xxxToken.getToken_type() + " " + xxxToken.getAccess_token();
redisTemplate.opsForValue().set("XXX:XXX:Token", token, 14000, TimeUnit.SECONDS);
// 返回结果
return token;
} catch (SocketTimeoutException e) {
log.error("获取Token请求超时异常,请求地址:{}", url);
return null;
} catch (Exception e) {
log.error("获取Token失败出现异常,请求结果:{},错误信息: {}", result, ExceptionUtil.getExceptionMessage(e));
return null;
}
}
application/json
/**
* 取消订单
*
* @param orderCode
* @return com.xxx.R<?>
* @throws Exception e
* @author wliduo[i@dolyw.com]
* @date 2020/5/13 17:21
*/
@Override
public R<String> cancelOrder(String orderCode) throws Exception {
// 封装订单参数
OrderReq orderReq = new OrderReq();
// 订单编号
orderReq.setOrderCode(orderCode);
// 备注
orderReq.setRemark("");
// Company
orderReq.setCompany(company);
// 客户编号
orderReq.setCno(cno);
// 开始发起请求,添加重试拦截器
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new CustomRetryInterceptor(maxRetry)).build();
// 请求地址,请求头和参数
String param = JSON.toJSONString(orderReq);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param);
Request request = new Request.Builder().url(baseUrl + cancelOrder).post(requestBody).build();
// 返回结果
String result = "";
// 发起请求
try (Response response = okHttpClient.newCall(request).execute()) {
// 获取结果
result = response.body().string();
log.info("请求地址:{},请求参数:{},请求结果:{}", baseUrl + cancelOrder, param, result);
CommonResp commonResp = JSON.parseObject(result, CommonResp.class);
// 服务商取消订单完成
return new R<>(commonResp.getStatus(), commonResp.getMsg(), orderCode);
} catch (SocketTimeoutException e) {
log.error("取消订单请求超时异常,请求地址:{},请求参数:{}", baseUrl + cancelOrder, param);
return new R<>(CommonResp.INTERNAL_SERVER_ERROR, "取消订单请求超时异常", orderCode);
} catch (Exception e) {
log.error("取消订单出现异常,请求结果:{},错误信息: {}", result, ExceptionUtil.getExceptionMessage(e));
return new R<>(CommonResp.INTERNAL_SERVER_ERROR, result, orderCode);
}
}
# 2. SpringBoot
SpringBoot 配置使用
# 2.1. Config
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
/**
* OkHttp3Config
*
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 10:10
*/
@Configuration
public class OkHttp3Config {
/**
* X509TrustManager
*
* @param
* @return javax.net.ssl.X509TrustManager
* @throws
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 10:15
*/
@Bean
public X509TrustManager x509TrustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}
/**
* SSLSocketFactory
*
* @param
* @return javax.net.ssl.SSLSocketFactory
* @throws
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 10:15
*/
@Bean
public SSLSocketFactory sslSocketFactory() {
try {
// 信任任何链接
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
/**
* 连接数量
*
* @param
* @return okhttp3.ConnectionPool
* @throws
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 10:15
*/
@Bean
public ConnectionPool pool() {
return new ConnectionPool(200, 5, TimeUnit.MINUTES);
}
/**
* 超时时间
*
* @param
* @return okhttp3.OkHttpClient
* @throws
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 10:15
*/
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory(), x509TrustManager())
// 禁用缓存,防止调用失败
// https://blog.csdn.net/u010248147/article/details/90479276
.retryOnConnectionFailure(true)
// 连接池
.connectionPool(pool())
.connectTimeout(60L, TimeUnit.SECONDS)
.readTimeout(60L, TimeUnit.SECONDS)
.build();
}
}
# 2.2. Helper
package com.pcic.helper;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Method;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
/**
* OkHttp3Helper
*
* @author wliduo[i@dolyw.com]
* @date 2021/8/23 10:08
*/
@Slf4j
@Component
public class OkHttp3Helper {
/**
* MEDIA_TYPE_JSON
*/
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
/**
* MEDIA_TYPE_TEXT
*/
public static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain;charset=utf-8");
@Autowired
private OkHttpClient okHttpClient;
/**
* Get请求
*
* @param url
* @return java.lang.String
* @throws
* @author wliduo[i@dolyw.com]
* @date 2021/8/23 10:18
*/
public String get(String url) {
String result = StrUtil.EMPTY;
Request request = new Request.Builder().url(url).build();
try (Response response = okHttpClient.newCall(request).execute()) {
result = response.body().string();
log.info("请求地址:{},请求结果:{}", url, result);
} catch (Exception e) {
log.error("请求地址:{},请求异常:{}", url, ExceptionUtil.stacktraceToOneLineString(e), e);
}
return result;
}
/**
* Post请求
*
* @param url
* @param data
* @param mediaType
* @return java.lang.String
* @throws
* @author wliduo[i@dolyw.com]
* @date 2021/8/23 10:18
*/
public String post(String url, String data, MediaType mediaType) {
return post(url, data, mediaType, null);
}
/**
* Post请求
*
* @param url
* @param data
* @param mediaType
* @param headers
* @return java.lang.String
* @throws
* @author wliduo[i@dolyw.com]
* @date 2021/8/23 10:18
*/
public String post(String url, String data, MediaType mediaType, Map<String, String> headers) {
String result = StrUtil.EMPTY;
RequestBody requestBody = RequestBody.create(mediaType, data);
Request.Builder builder = new Request.Builder();
if (headers != null && headers.size() > 0) {
for (Map.Entry entry : headers.entrySet()) {
builder.header(entry.getKey().toString(), entry.getValue().toString());
}
}
Request request = builder.url(url).post(requestBody).build();
try (Response response = okHttpClient.newCall(request).execute()) {
result = response.body().string();
log.info("请求地址:{},请求参数:{},请求结果:{}", url, data, result);
} catch (IOException e) {
log.error("请求地址:{},请求参数:{},请求异常:{}", url, data, ExceptionUtil.stacktraceToOneLineString(e), e);
}
return result;
}
/**
* http请求
*
* @param url
* @param data
* @param request
* @return java.lang.String
* @throws
* @author wliduo[i@dolyw.com]
* @date 2022/7/14 13:40
*/
public String http(String url, String data, HttpServletRequest request) {
String result = StrUtil.EMPTY;
// ContentType处理
MediaType mediaType = MediaType.parse(request.getHeader(HttpHeaders.CONTENT_TYPE) + "; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaType, data);
Request.Builder builder = new Request.Builder();
// Header处理
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
builder.header(headerName, request.getHeader(headerName));
}
// Method处理
String method = request.getMethod().toUpperCase();
Request.Builder requestBuild = builder.url(url);
if (Method.POST.toString().equals(method)) {
requestBuild.post(requestBody);
}
if (Method.PUT.toString().equals(method)) {
requestBuild.put(requestBody);
}
if (Method.DELETE.toString().equals(method)) {
requestBuild.delete(requestBody);
}
try (Response response = okHttpClient.newCall(requestBuild.build()).execute()) {
result = response.body().string();
log.info("请求地址:{},请求参数:{},请求结果:{}", url, data, result);
} catch (IOException e) {
log.error("请求地址:{},请求参数:{},请求异常:{}", url, data, ExceptionUtil.stacktraceToOneLineString(e), e);
}
return result;
}
}
参考