OkHttp使用
2023-07-06
OkHttp使用
介绍
OkHttp是一个网络应用编程工具,适用于 Android 5.0+(API 级别 21+)和 Java 8+。
官方链接:https://square.github.io/okhttp/
java中使用
maven中引入:
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
<!--常用工具集-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
HttpClientUtil 代码,其中 HttpRequestException 与 RetryFunction 为自定义类
HttpRequestException 为http请求的全局异常,RetryFunction为重试函数, 包含参数重试次数与重试间隔(秒)
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.json.JSONUtil;
import common.exception.HttpRequestException;
import okhttp3.*;
import java.io.IOException;
import java.net.Proxy;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class HttpClientUtil {
private volatile static HttpClientUtil httpClientUtil;
private OkHttpClient httpClient = null;
static final MediaType JSON_TYPE = MediaType.parse("application/json");
private HttpClientUtil() {
}
/**
* 生成一个 httpClientUtil实例,初始化 okhttpClient参数
*
* @return
*/
public static synchronized HttpClientUtil getInstance() {
if (httpClientUtil == null) {
httpClientUtil = new HttpClientUtil();
}
httpClientUtil.initOkHttpClient();
return httpClientUtil;
}
public HttpClientUtil initOkHttpClient() {
OkHttpClient.Builder builder;
if (this.httpClient == null) {
builder = new OkHttpClient.Builder();
} else {
builder = httpClient.newBuilder();
}
this.httpClient = builder
.connectionPool(new ConnectionPool(200, 10, TimeUnit.SECONDS))
.connectTimeout(2, TimeUnit.SECONDS)
.readTimeout(2, TimeUnit.SECONDS)
.build();
return this;
}
public HttpClientUtil initOkHttpClient(Proxy proxy, Authenticator authenticator) {
this.httpClient = httpClient.newBuilder()
.connectionPool(new ConnectionPool(200, 10, TimeUnit.SECONDS))
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.proxy(proxy)
.proxyAuthenticator(authenticator)
.build();
return this;
}
public String doGet(String url, Map<String, Object> params) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(UrlBuilder.ofHttp(url).build()).newBuilder();
if (MapUtil.isNotEmpty(params)) {
params.forEach((k, v) -> {
urlBuilder.addQueryParameter(k, v.toString());
});
}
Request.Builder reqBuild = new Request.Builder();
reqBuild.url(urlBuilder.build());
Response response = RetryFunction.retry(5, 1, () -> {
try {
return httpClient.newCall(reqBuild.build()).execute();
} catch (IOException e) {
throw new RuntimeException("http get请求执行异常,url=" + url, e);
}
});
return checkResponse(response);
}
public String doPost(String url, Map<String, Object> params) {
RequestBody body = RequestBody.create(JSON_TYPE, JSONUtil.toJsonStr(params));
Request.Builder reqBuild = new Request.Builder().url(url).post(body);
Response response = RetryFunction.retry(5, 1, () -> {
try {
return httpClient.newCall(reqBuild.build()).execute();
} catch (IOException e) {
throw new RuntimeException("http post请求执行异常,url=" + url, e);
}
});
return checkResponse(response);
}
private String checkResponse(Response response) {
try {
return response.body().string();
} catch (IOException e) {
throw new HttpRequestException("http结果解析异常,解析内容为:" + response, e);
}
}
}
import common.exception.RetryException;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Supplier;
@Slf4j
public class RetryFunction<R> {
public static <R> R retry(long retryCount, long interval, Supplier<R> supplier){
Long retryCountBack = retryCount;
Boolean success = Boolean.FALSE;
R result = null;
//还有重试次数并且未成功的时候
while (retryCount > 0 && !success) {
try {
result = supplier.get();
if(result != null){
success = Boolean.TRUE;
}
}catch (Exception e){
log.error("接口请求失败,本次错误的信息为:{}, 剩余尝试次数为:{}", e.getMessage(), retryCount);
}
retryCount--;
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if(result == null){
throw new RetryException("接口尝试"+ retryCountBack +"次后依然失败。");
}
return result;
}
}
public class HttpRequestException extends RuntimeException{
public HttpRequestException() {
}
public HttpRequestException(String message) {
super(message);
}
public HttpRequestException(String message, Throwable cause) {
super(message, cause);
}
public HttpRequestException(Throwable cause) {
super(cause);
}
public HttpRequestException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
创建实例方法,可按情况是否使用代理发起请求
import common.util.HttpClientUtil;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
@Configuration
public class HttpClientConfig {
@Value("${proxy.hostname}")
private String hostname;
@Value("${proxy.port}")
private Integer port;
@Value("${proxy.username}")
private String username;
@Value("${proxy.password}")
private String password;
@Bean
HttpClientUtil client(){
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(hostname, port));
Authenticator authenticator = null;
if(username != null){
authenticator = (route, response) -> response.request().newBuilder()
.header("Proxy-Authorization", Credentials.basic(username, password))
.build();
}
return HttpClientUtil.getInstance().initOkHttpClient(proxy, authenticator);
}
}