HTTP connection client, choose HttpClient or OkHttp?

Author: is he Tiantian there https://www.jianshu.com/p/68c30beca612

Written in front

Why do you write this article? It's because of chatting with friends

This has touched my knowledge blind area again. First, I have a wave of Baidu oriented learning. I search directly according to the difference and performance comparison between the keyword httpclient and okhttp. I didn't find the desired answer. So I went to the overstackflow to see if someone asked this question, which will not disappoint you

So compare the usage, performance and timeout configuration

Use

HttpClient and OkHttp are generally used to call other services. Generally, the exposed interfaces of 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

Introduction to HttpClient

Using HttpClient to send requests is mainly divided into the following steps:

  • Create the CloseableHttpClient object, which is synchronous and the closeablehttapasyncclient object, which is asynchronous

  • Create Http request object

  • Call the execute method to execute the request. If it is an asynchronous request, call the start method before execution

Create connection:

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

The connection is synchronous

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, and 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, which needs 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/Study/docker_practice.pdf");  
    FileBody fileBody = new FileBody(file);  
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);  
    builder.addPart("file", fileBody);  //addPart upload file  
    HttpEntity entity = builder.build();  
    httpPost.setEntity(entity);  
    CloseableHttpResponse response = httpClient.execute(httpPost);  
    System.out.println(EntityUtils.toString(response.getEntity()));  
}  

Upload files through 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()));  
}  

Requested cancellation:

@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);  //Set timeout  
    //Cancel test connection  
  
    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 the 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...[Ellipsis]  

OkHttp use

Using OkHttp to send a request is mainly divided into the following steps:

  • Create OkHttpClient object

  • Create Request object

  • Encapsulate the Request object as a Call

  • Synchronous or asynchronous requests are executed through Call, synchronous execution is called by execute method, and asynchronous execution is called by enqueue method

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);  
    //Request parameters  
    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);  
    //Request parameters  
    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 request  
           .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/Study/docker_practice.pdf")))  
            .build();  
    Request request = new Request.Builder()  
            .url(url)  
            .post(requestBody)  //The default is GET request, which can not be written  
            .build();  
    final Call call = client.newCall(request);  
    Response response = call.execute();  
    System.out.println(response.body().string());  
}  

Upload the file by simulating the form with addFormDataPart method

DELETE request:

@Test  
public void testDelete() throws IOException {  
  String url = String.format("%s%s", BASE_URL, api);  
  //Request parameters  
  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());  
}  

Requested cancellation:

@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();  
    //Cancel test connection  
    while (true) {  
         //Cancel the request if the result is less than 1 minute  
        if (System.currentTimeMillis() - start > 1000) {  
            call.cancel();  
            System.out.println("task canceled");  
            break;  
        }  
    }  
  
    System.out.println(response.body().string());  
}  

Call cancel method to cancel the test result:

task canceled  
cost 9110 msc  
  
java.net.SocketException: socket closed...[Ellipsis]  

Summary

OkHttp uses the build mode to create objects more succinctly, and uses the. post/.delete/.put/.get method to represent the request type. There is no need to create HttpGet, HttpPost and other methods like HttpClient to create the request type

On the dependency package, if HttpClient needs to send asynchronous requests and upload files, it needs to introduce additional asynchronous request dependency

 <!---File upload-->  
 <dependency>  
     <groupId>org.apache.httpcomponents</groupId>  
     <artifactId>httpmime</artifactId>  
     <version>4.5.3</version>  
 </dependency>  
 <!--Asynchronous request-->  
 <dependency>  
     <groupId>org.apache.httpcomponents</groupId>  
     <artifactId>httpasyncclient</artifactId>  
     <version>4.5.3</version>  
 </dependency>  

To cancel a request, HttpClient uses the abort method, OkHttp uses the cancel method, which is quite simple. If asynchronous client is used, the method to cancel the request can be called when an exception is thrown

Timeout settings

HttpClient timeout setting:

After HttpClient4.3 +, 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);  //Set timeout  

Timeout is set on request type HttpGet, not HttpClient

OkHttp timeout setting:

Set directly on OkHttp

private OkHttpClient client = new OkHttpClient.Builder()  
        .connectTimeout(60, TimeUnit.SECONDS)//Set connection timeout  
        .readTimeout(60, TimeUnit.SECONDS)//Set read timeout  
        .build();  

Summary:

If the client is in singleton mode, HttpClient is more flexible in setting timeout. Different timeout times are set for different request types. Once the timeout time is set for OkHttp, the timeout time of all request types will be determined

Performance comparison between HttpClient and OkHttp

Test environment:

  • CPU six core

  • Memory 8G

  • windows10

Each test case is tested five times, excluding chance

The client connection is a single example:

client connection is not a single example:

In the single instance mode, the response speed of HttpClient is faster, in milliseconds, with little difference in performance

In non singleton mode, the performance of OkHttp is better, and HttpClient takes a long time to create a connection. Because most of these resources will be written in singleton mode, the test results in Figure 1 are more valuable.

summary

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

Recommend to my blog to read more

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

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

3.Maven, Git, Eclipse, Intellij IDEA series tools tutorial

4.Latest interview questions of Java, backend, architecture, Alibaba and other large factories

Life is beautiful. See you tomorrow

Tags: Programming OkHttp JSON Java socket

Posted on Sun, 08 Mar 2020 06:19:37 -0400 by brokeDUstudent