Java中的OkHttp使用教程
什么是OKHttp
一般在Java平臺(tái)上,我們會(huì)使用Apache HttpClient作為Http客戶端,用于發(fā)送 HTTP 請求,并對(duì)響應(yīng)進(jìn)行處理。比如可以使用http客戶端與第三方服務(wù)(如SSO服務(wù))進(jìn)行集成,當(dāng)然還可以爬取網(wǎng)上的數(shù)據(jù)等。OKHttp與HttpClient類似,也是一個(gè)Http客戶端,提供了對(duì) HTTP/2 和 SPDY 的支持,并提供了連接池,GZIP 壓縮和 HTTP 響應(yīng)緩存功能;
OkHttp是目前非?;鸬木W(wǎng)絡(luò)庫,它有以下特性:
1.支持HTTP/2,允許所有同一個(gè)主機(jī)地址的請求共享同一個(gè)socket連接
2.連接池減少請求延時(shí)
3.透明的GZIP壓縮減少響應(yīng)數(shù)據(jù)的大小
4.緩存響應(yīng)內(nèi)容,避免一些完全重復(fù)的請求
OkHttp基本使用
- OkHttpClient:客戶端對(duì)象
- Request:訪問請求,Post請求中需要包含RequestBody
- RequestBody:請求數(shù)據(jù),在Post請求中用到
- Response:即網(wǎng)絡(luò)請求的響應(yīng)結(jié)果
- MediaType:數(shù)據(jù)類型,用來表明數(shù)據(jù)是json,image,pdf等一系列格式
- client.newCall(request).execute():同步的請求方法
- client.newCall(request).enqueue(Callback callBack):異步的請求方法,但Callback是執(zhí)行在子線程中的,因此不能在此進(jìn)行UI更新操作
官網(wǎng):http://square.github.io/okhttp/
添加依賴
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>OkHttp工具類
package com.loginsimpl.utils;
import com.alibaba.fastjson.JSON;
import okhttp3.*;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class OkHttpUtils {
private static volatile OkHttpClient okHttpClient = null;
private static volatile Semaphore semaphore = null;
private Map<String, String> headerMap;
private Map<String, String> paramMap;
private String url;
private Request.Builder request;
/**
* 初始化okHttpClient,并且允許https訪問
*/
private OkHttpUtils() {
if (okHttpClient == null) {
synchronized (OkHttpUtils.class) {
if (okHttpClient == null) {
TrustManager[] trustManagers = buildTrustManagers();
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
.hostnameVerifier((hostName, session) -> true)
.retryOnConnectionFailure(true)
.build();
addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
}
}
}
}
/**
* 用于異步請求時(shí),控制訪問線程數(shù),返回結(jié)果
*
* @return
*/
private static Semaphore getSemaphoreInstance() {
//只能1個(gè)線程同時(shí)訪問
synchronized (OkHttpUtils.class) {
if (semaphore == null) {
semaphore = new Semaphore(0);
}
}
return semaphore;
}
/**
* 創(chuàng)建OkHttpUtils
*
* @return
*/
public static OkHttpUtils builder() {
return new OkHttpUtils();
}
/**
* 添加url
*
* @param url
* @return
*/
public OkHttpUtils url(String url) {
this.url = url;
return this;
}
/**
* 添加參數(shù)
*
* @param key 參數(shù)名
* @param value 參數(shù)值
* @return
*/
public OkHttpUtils addParam(String key, String value) {
if (paramMap == null) {
paramMap = new LinkedHashMap<>(16);
}
paramMap.put(key, value);
return this;
}
/**
* 添加請求頭
*
* @param key 參數(shù)名
* @param value 參數(shù)值
* @return
*/
public OkHttpUtils addHeader(String key, String value) {
if (headerMap == null) {
headerMap = new LinkedHashMap<>(16);
}
headerMap.put(key, value);
return this;
}
/**
* 初始化get方法
*
* @return
*/
public OkHttpUtils get() {
request = new Request.Builder().get();
StringBuilder urlBuilder = new StringBuilder(url);
if (paramMap != null) {
urlBuilder.append("?");
try {
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).
append("=").
append(URLEncoder.encode(entry.getValue(), "utf-8")).
append("&");
}
} catch (Exception e) {
e.printStackTrace();
}
urlBuilder.deleteCharAt(urlBuilder.length() - 1);
}
request.url(urlBuilder.toString());
return this;
}
/**
* 初始化post方法
*
* @param isJsonPost true等于json的方式提交數(shù)據(jù),類似postman里post方法的raw
* false等于普通的表單提交
* @return
*/
public OkHttpUtils post(boolean isJsonPost) {
RequestBody requestBody;
if (isJsonPost) {
String json = "";
if (paramMap != null) {
json = JSON.toJSONString(paramMap);
}
requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
} else {
FormBody.Builder formBody = new FormBody.Builder();
if (paramMap != null) {
paramMap.forEach(formBody::add);
}
requestBody = formBody.build();
}
request = new Request.Builder().post(requestBody).url(url);
return this;
}
/**
* 同步請求
*
* @return
*/
public String sync() {
setHeader(request);
try {
Response response = okHttpClient.newCall(request.build()).execute();
assert response.body() != null;
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
return "請求失?。? + e.getMessage();
}
}
/**
* 異步請求,有返回值 (限流的,同一時(shí)間只允許一個(gè)訪問,其他等待)
*/
public String async() {
StringBuilder buffer = new StringBuilder("");
setHeader(request);
okHttpClient.newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
buffer.append("請求出錯(cuò):").append(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
assert response.body() != null;
buffer.append(response.body().string());
getSemaphoreInstance().release();
}
});
try {
getSemaphoreInstance().acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
return buffer.toString();
}
/**
* 異步請求,帶有接口回調(diào)
*
* @param callBack
*/
public void async(ICallBack callBack) {
setHeader(request);
okHttpClient.newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFailure(call, e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
assert response.body() != null;
callBack.onSuccessful(call, response.body().string());
}
});
}
/**
* 為request添加請求頭
*
* @param request
*/
private void setHeader(Request.Builder request) {
if (headerMap != null) {
try {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
request.addHeader(entry.getKey(), entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 生成安全套接字工廠,用于https請求的證書跳過
*
* @return
*/
private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return ssfFactory;
}
private static TrustManager[] buildTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
/**
* 自定義一個(gè)接口回調(diào)
*/
public interface ICallBack {
void onSuccessful(Call call, String data);
void onFailure(Call call, String errorMsg);
}
}
使用案例
發(fā)送get請求
String sync = OkHttpUtils.builder().url("http://localhost:9100/user/all")
.addHeader("token", "xxxxxxx")
.addParam("name", "xxx").addParam("pass", "xxx")
.get()
.sync();
System.out.println(sync);
發(fā)送Post請求
String sync = OkHttpUtils.builder().url("http://localhost:9100/user/all")
.addHeader("token", "xxxxxxx")
.addParam("name", "xxx").addParam("pass", "xxx")
.post(true) // true 為json提交方式
.sync();
System.out.println(sync);
發(fā)送異步請求
需要實(shí)現(xiàn)ICallBack接口
//回調(diào)實(shí)現(xiàn)類
public class AsyncHttpServiceImpl implements OkHttpUtils.ICallBack {
@Override
public void onSuccessful(Call call, String data) {
//接口正常返回的內(nèi)容
System.out.println("onSuccessful"+data);
}
@Override
public void onFailure(Call call, String errorMsg) {
//接口錯(cuò)誤返回的內(nèi)容
System.out.println("onFailure"+errorMsg);
}
}
發(fā)送異步請求
OkHttpUtils.builder().url("http://localhost:9100/user/all")
.addHeader("token", "xxxxxxx")
.addParam("name", "xxx").addParam("pass", "xxx")
.post(true)
.async(new AsyncHttpServiceImpl());
到此這篇關(guān)于Java-OkHttp使用教程的文章就介紹到這了,更多相關(guān)Java-OkHttp使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot自動(dòng)配置的原理及@Conditional條件注解
這篇文章主要介紹了Spring?Boot自動(dòng)配置的原理及@Conditional條件注解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的朋友可以參考一下2022-07-07
???????Spring多租戶數(shù)據(jù)源管理 AbstractRoutingDataSource
本文技術(shù)了???????Spring多租戶數(shù)據(jù)源管理 AbstractRoutingDataSource,下文詳細(xì)內(nèi)容介紹,需要的小伙伴可以參考一下2022-05-05
Java飛行記錄器JFR功能實(shí)現(xiàn)過程圖解
這篇文章主要介紹了Java飛行記錄器JFR功能實(shí)現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Java定時(shí)任務(wù):利用java Timer類實(shí)現(xiàn)定時(shí)執(zhí)行任務(wù)的功能
本篇文章主要介紹了利用java Timer類實(shí)現(xiàn)定時(shí)執(zhí)行任務(wù)的功能,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11
Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度下載文件
這篇文章主要為大家詳細(xì)介紹了Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度下載文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
http調(diào)用controller方法時(shí)openfeign執(zhí)行流程
這篇文章主要為大家介紹了http調(diào)用controller方法時(shí)openfeign執(zhí)行流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07

