HTTP connection client, choose HttpClient or OkHttp?

Author: Dr sweet in it https://www.jianshu.com/p/68c30beca612

Write in front

Why did you write this article because of chatting with friends

This touched my knowledge blind spot again. First of all, I went to Baidu to learn. I searched directly based on the difference between the keywords httpclient and okhttp, and compared the performance. I did n’t find the answer I wanted. I have asked this question and I will not let you down

So compare in terms of usage, performance, timeout configuration

use

HttpClient and OkHttp are generally used to call other services. The interfaces exposed by general services are http, and the common request types of http are GET, PUT, POST, and DELETE. Therefore, the call of these request types is mainly introduced.

HttpClient introduction

Sending a request using HttpClient is mainly divided into the following steps:

  • Create CloseableHttpClient object or CloseableHttpAsyncClient object, the former is synchronous, the latter is asynchronous

  • Create Http request object

  • Call the execute method to execute the request, if it is an asynchronous request, you need to call the start method before executing

Create connection:

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

This connection is a synchronous connection

GET request:

@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()));  
}  

Use HttpGet to indicate that the connection is a GET request, HttpClient calls the execute method to send the GET request

PUT request:

@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 request:

Add object

@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()));  
}  

The request is a request to create an object, you need to pass in a json string

upload files

@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()));  
}  

Upload files via addPart

DELETE request:

@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()));  
}  

Cancellation requested:

@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()));  
}  

Call abort method to cancel the request execution result:

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

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

OkHttp use

Sending requests using OkHttp is mainly divided into the following steps:

  • Create OkHttpClient object

  • Create Request object

  • Encapsulate Request object as Call

  • Use Call to execute synchronous or asynchronous request, call execute method to execute synchronously, call enqueue method to execute asynchronously

Create connection:

private OkHttpClient client = new OkHttpClient();  

GET request:

@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 request:

@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 request:

Add object

@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());  
}  

upload files

@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());  
}  

Use the addFormDataPart method to simulate the form upload file

DELETE request:

@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());  
}  

Cancellation requested:

@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());  
}  

Call the cancel method to cancel the test results:

task canceled  
cost 9110 msc  

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

summary

OkHttp uses the build mode to create objects more concisely, and uses the .post / .delete / .put / .get method to indicate the request type. There is no need for methods such as HttpClient to create HttpGet and HttpPost to create request types

On the dependency package, if HttpClient needs to send asynchronous requests and realize file upload, additional asynchronous request dependencies need to be introduced

 <!---文件上传-->  
 <dependency>  
     <groupId>org.apache.httpcomponents</groupId>  
     <artifactId>httpmime</artifactId>  
     <version>4.5.3</version>  
 </dependency>  
 <!--异步请求-->  
 <dependency>  
     <groupId>org.apache.httpcomponents</groupId>  
     <artifactId>httpasyncclient</artifactId>  
     <version>4.5.3</version>  
 </dependency>  

To cancel the request, HttpClient uses the abort method and OkHttp uses the cancel method. It is quite simple. If you are using an asynchronous client, you can call the method to cancel the request when an exception is thrown.

Timeout setting

HttpClient timeout setting:

In HttpClient 4.3+ and above, the timeout setting is set through 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);  //设置超时时间  

The timeout is set on the request type HttpGet, not HttpClient

OkHttp timeout setting:

Set directly on OkHttp

private OkHttpClient client = new OkHttpClient.Builder()  
        .connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间  
        .readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间  
        .build();  

summary:

If the client is in singleton mode, HttpClient is more flexible in setting timeouts, and sets different timeout times for different request types. Once OkHttp sets the timeout time, the timeout time for all request types is also determined

HttpClient and OkHttp performance comparison

test environment:

  • CPU six core

  • Memory 8G

  • windows10

Each test case is tested five times, excluding chance

The client connection is a singleton:

Client connection is not a singleton:

In singleton mode, the response speed of HttpClient is faster, the unit is milliseconds, the performance difference is not much different

In non-singleton mode, OkHttp performs better, and HttpClient takes more time to create a connection, because in most cases these resources will be written in singleton mode, so the test results in Figure 1 are more valuable.

to sum up

OkHttp and HttpClient are indistinguishable in performance and use, and can be selected according to the actual business.

I recommend going to my blog to read more:

1. Java JVM, collection, multithreading, new features series tutorials

2. Spring MVC, Spring Boot, Spring Cloud series of tutorials

3. Maven, Git, Eclipse, Intellij IDEA series of tool tutorials

4. The latest interview questions for Java, backend, architecture, Alibaba and other major manufacturers

Life is beautiful, see you tomorrow ~

Published 474 original articles · praised 1030 · 1.45 million views +

Guess you like

Origin blog.csdn.net/youanyyou/article/details/105431797