日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp?

發布時間:2024/4/11 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

你知道的越多,不知道的就越多,業余的像一棵小草!

你來,我們一起精進!你不來,我和你的競爭對手一起精進!

編輯:業余草

來源:juejin.im/post/6844904040644476941

推薦:https://www.xttblog.com/?p=5097

寫在前面

為什么會寫這篇文章,起因于和朋友的聊天


這又觸及到我的知識盲區了,首先來一波面向百度學習,直接根據關鍵字 httpclient 和 okhttp 的區別、性能比較進行搜索,沒有找到想要的答案,于是就去 overstackflow 上看看是不是有人問過這個問題,果然不會讓你失望的


所以從使用、性能、超時配置方面進行比較

使用

HttpClient 和 OkHttp 一般用于調用其它服務,一般服務暴露出來的接口都為 http,http 常用請求類型就為 GET、PUT、POST 和 DELETE,因此主要介紹這些請求類型的調用

HttpClient 使用介紹

使用 HttpClient 發送請求主要分為一下幾步驟:

  • 創建 CloseableHttpClient 對象或 CloseableHttpAsyncClient 對象,前者同步,后者為異步
  • 創建 Http 請求對象
  • 調用 execute 方法執行請求,如果是異步請求在執行之前需調用 start 方法

創建連接:

CloseableHttpClient?httpClient?=?HttpClientBuilder.create().build();

該連接為同步連接

GET 請求:

@Test
public?void?testGet()?throws?IOException?{
????String?api?=?"/api/files/1";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????HttpGet?httpGet?=?new?HttpGet(url);
????CloseableHttpResponse?response?=?httpClient.execute(httpGet);
????System.out.println(EntityUtils.toString(response.getEntity()));
}

使用 HttpGet 表示該連接為 GET 請求,HttpClient 調用 execute 方法發送 GET 請求

PUT 請求:

@Test
public?void?testPut()?throws?IOException?{
????String?api?=?"/api/user";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????HttpPut?httpPut?=?new?HttpPut(url);
????UserVO?userVO?=?UserVO.builder().name("h2t").id(16L).build();
????httpPut.setHeader("Content-Type",?"application/json;charset=utf8");
????httpPut.setEntity(new?StringEntity(JSONObject.toJSONString(userVO),?"UTF-8"));
????CloseableHttpResponse?response?=?httpClient.execute(httpPut);
????System.out.println(EntityUtils.toString(response.getEntity()));
}

POST 請求:

  • 添加對象
@Test
public?void?testPost()?throws?IOException?{
?String?api?=?"/api/user";
?String?url?=?String.format("%s%s",?BASE\_URL,?api);
?HttpPost?httpPost?=?new?HttpPost(url);
?UserVO?userVO?=?UserVO.builder().name("h2t2").build();
?httpPost.setHeader("Content-Type",?"application/json;charset=utf8");
?httpPost.setEntity(new?StringEntity(JSONObject.toJSONString(userVO),?"UTF-8"));
?CloseableHttpResponse?response?=?httpClient.execute(httpPost);
?System.out.println(EntityUtils.toString(response.getEntity()));
}

該請求是一個創建對象的請求,需要傳入一個 json 字符串

  • 上傳文件
@Test
public?void?testUpload1()?throws?IOException?{
?String?api?=?"/api/files/1";
?String?url?=?String.format("%s%s",?BASE\_URL,?api);
?HttpPost?httpPost?=?new?HttpPost(url);
?File?file?=?new?File("C:/Users/hetiantian/Desktop/學習/docker\_practice.pdf");
?FileBody?fileBody?=?new?FileBody(file);
?MultipartEntityBuilder?builder?=?MultipartEntityBuilder.create();
?builder.setMode(HttpMultipartMode.BROWSER\_COMPATIBLE);
?builder.addPart("file",?fileBody);??//addPart上傳文件
?HttpEntity?entity?=?builder.build();
?httpPost.setEntity(entity);
?CloseableHttpResponse?response?=?httpClient.execute(httpPost);
?System.out.println(EntityUtils.toString(response.getEntity()));
}

通過 addPart 上傳文件

DELETE 請求:

@Test
public?void?testDelete()?throws?IOException?{
????String?api?=?"/api/user/12";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????HttpDelete?httpDelete?=?new?HttpDelete(url);
????CloseableHttpResponse?response?=?httpClient.execute(httpDelete);
????System.out.println(EntityUtils.toString(response.getEntity()));
}

請求的取消:

@Test
public?void?testCancel()?throws?IOException?{
????String?api?=?"/api/files/1";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????HttpGet?httpGet?=?new?HttpGet(url);
????httpGet.setConfig(requestConfig);??//設置超時時間
????//測試連接的取消

????long?begin?=?System.currentTimeMillis();
????CloseableHttpResponse?response?=?httpClient.execute(httpGet);
????while?(true)?{
????????if?(System.currentTimeMillis()?-?begin?>?1000)?{
??????????httpGet.abort();
??????????System.out.println("task?canceled");
??????????break;
??????}
????}

????System.out.println(EntityUtils.toString(response.getEntity()));
}

調用 abort 方法取消請求 執行結果:

task?canceled
cost?8098?msc
Disconnected?from?the?target?VM,?address:?'127.0.0.1:60549',?transport:?'socket'

java.net.SocketException:?socket?closed...【省略】

OkHttp 使用

使用 OkHttp 發送請求主要分為一下幾步驟:

  • 創建 OkHttpClient 對象
  • 創建 Request 對象
  • 將 Request 對象封裝為 Call
  • 通過 Call 來執行同步或異步請求,調用 execute 方法同步執行,調用 enqueue 方法異步執行

創建連接:

private?OkHttpClient?client?=?new?OkHttpClient();

GET 請求:

@Test
public?void?testGet()?throws?IOException?{
????String?api?=?"/api/files/1";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????Request?request?=?new?Request.Builder()
????????????.url(url)
????????????.get()
????????????.build();
????final?Call?call?=?client.newCall(request);
????Response?response?=?call.execute();
????System.out.println(response.body().string());
}

PUT 請求:

@Test
public?void?testPut()?throws?IOException?{
????String?api?=?"/api/user";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????//請求參數
????UserVO?userVO?=?UserVO.builder().name("h2t").id(11L).build();
????RequestBody?requestBody?=?RequestBody.create(MediaType.parse("application/json;?charset=utf-8"),
????JSONObject.toJSONString(userVO));
????Request?request?=?new?Request.Builder()
????????????.url(url)
????????????.put(requestBody)
????????????.build();
????final?Call?call?=?client.newCall(request);
????Response?response?=?call.execute();
????System.out.println(response.body().string());
}

POST 請求:

  • 添加對象
@Test
public?void?testPost()?throws?IOException?{
?String?api?=?"/api/user";
?String?url?=?String.format("%s%s",?BASE\_URL,?api);
?//請求參數
?JSONObject?json?=?new?JSONObject();
?json.put("name",?"hetiantian");
?RequestBody?requestBody?=?RequestBody.create(MediaType.parse("application/json;?charset=utf-8"),?????String.valueOf(json));
?Request?request?=?new?Request.Builder()
???.url(url)
???.post(requestBody)?//post請求
?????.build();
?final?Call?call?=?client.newCall(request);
?Response?response?=?call.execute();
?System.out.println(response.body().string());
}
  • 上傳文件
@Test
public?void?testUpload()?throws?IOException?{
?String?api?=?"/api/files/1";
?String?url?=?String.format("%s%s",?BASE\_URL,?api);
?RequestBody?requestBody?=?new?MultipartBody.Builder()
???.setType(MultipartBody.FORM)
???.addFormDataPart("file",?"docker\_practice.pdf",
?????RequestBody.create(MediaType.parse("multipart/form-data"),
???????new?File("C:/Users/hetiantian/Desktop/學習/docker\_practice.pdf")))
???.build();
?Request?request?=?new?Request.Builder()
???.url(url)
???.post(requestBody)??//默認為GET請求,可以不寫
???.build();
?final?Call?call?=?client.newCall(request);
?Response?response?=?call.execute();
?System.out.println(response.body().string());
}

通過 addFormDataPart 方法模擬表單方式上傳文件

DELETE 請求:

@Test
public?void?testDelete()?throws?IOException?{
??String?url?=?String.format("%s%s",?BASE\_URL,?api);
??//請求參數
??Request?request?=?new?Request.Builder()
??????????.url(url)
??????????.delete()
??????????.build();
??final?Call?call?=?client.newCall(request);
??Response?response?=?call.execute();
??System.out.println(response.body().string());
}

請求的取消:

@Test
public?void?testCancelSysnc()?throws?IOException?{
????String?api?=?"/api/files/1";
????String?url?=?String.format("%s%s",?BASE\_URL,?api);
????Request?request?=?new?Request.Builder()
????????????.url(url)
????????????.get()
????????????.build();
????final?Call?call?=?client.newCall(request);
????Response?response?=?call.execute();
????long?start?=?System.currentTimeMillis();
????//測試連接的取消
????while?(true)?{
?????????//1分鐘獲取不到結果就取消請求
????????if?(System.currentTimeMillis()?-?start?>?1000)?{
????????????call.cancel();
????????????System.out.println("task?canceled");
????????????break;
????????}
????}

????System.out.println(response.body().string());
}

調用 cancel 方法進行取消 測試結果:

task?canceled
cost?9110?msc

java.net.SocketException:?socket?closed...【省略】

小結

  • OkHttp 使用 build 模式創建對象來的更簡潔一些,并且使用. post/.delete/.put/.get 方法表示請求類型,不需要像 HttpClient 創建 HttpGet、HttpPost 等這些方法來創建請求類型
  • 依賴包上,如果 HttpClient 需要發送異步請求、實現文件上傳,需要額外的引入異步請求依賴
?
?<dependency>
??<groupId>org.apache.httpcomponentsgroupId>
??<artifactId>httpmimeartifactId>
??<version>4.5.3version>
?dependency>
?
?<dependency>
??<groupId>org.apache.httpcomponentsgroupId>
??<artifactId>httpasyncclientartifactId>
??<version>4.5.3version>
?dependency>
  • 請求的取消,HttpClient 使用 abort 方法,OkHttp 使用 cancel 方法,都挺簡單的,如果使用的是異步 client,則在拋出異常時調用取消請求的方法即可

超時設置

HttpClient 超時設置:在 HttpClient4.3 + 版本以上,超時設置通過 RequestConfig 進行設置

private?CloseableHttpClient?httpClient?=?HttpClientBuilder.create().build();
private?RequestConfig?requestConfig?=??RequestConfig.custom()
????????.setSocketTimeout(60?\*?1000)
????????.setConnectTimeout(60?\*?1000).build();
String?api?=?"/api/files/1";
String?url?=?String.format("%s%s",?BASE\_URL,?api);
HttpGet?httpGet?=?new?HttpGet(url);
httpGet.setConfig(requestConfig);??//設置超時時間

超時時間是設置在請求類型 HttpGet 上,而不是 HttpClient 上

OkHttp 超時設置:直接在 OkHttp 上進行設置

private?OkHttpClient?client?=?new?OkHttpClient.Builder()
????????.connectTimeout(60,?TimeUnit.SECONDS)//設置連接超時時間
????????.readTimeout(60,?TimeUnit.SECONDS)//設置讀取超時時間
????????.build();

小結:如果 client 是單例模式,HttpClient 在設置超時方面來的更靈活,針對不同請求類型設置不同的超時時間,OkHttp 一旦設置了超時時間,所有請求類型的超時時間也就確定

HttpClient 和 OkHttp 性能比較

測試環境:

  • CPU 六核
  • 內存 8G
  • windows10

每種測試用例都測試五次,排除偶然性

client 連接為單例:

img

client 連接不為單例:

img

單例模式下,HttpClient 的響應速度要更快一些,單位為毫秒,性能差異相差不大 非單例模式下,OkHttp 的性能更好,HttpClient 創建連接比較耗時,因為多數情況下這些資源都會寫成單例模式,因此圖一的測試結果更具有參考價值

總結

OkHttp 和 HttpClient 在性能和使用上不分伯仲,根據實際業務選擇即可

總結

以上是生活随笔為你收集整理的httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。