Соединение с HTTP-клиентом, выберите HttpClient или OkHttp?

Java
Соединение с HTTP-клиентом, выберите HttpClient или OkHttp?

написать впереди

Зачем писать эту статью, из-за общения с друзьями

Это снова коснулось моего слепого пятна в знаниях. Прежде всего, я буду учиться у Baidu. Я искал напрямую, основываясь на разнице и сравнении производительности между ключевыми словами httpclient и okhttp. Задайте этот вопрос, вы не будете разочарованы
Поэтому сравните с точки зрения использования, производительности и конфигурации времени ожидания.

использовать

HttpClient и OkHttp обычно используются для вызова других служб. Интерфейсы, предоставляемые общими службами, — это http. Распространенными типами запросов http являются GET, PUT, POST и DELETE. Поэтому вызов этих типов запросов в основном представлен.

Введение в использование HttpClient

Отправка запросов с помощью HttpClient в основном делится на следующие этапы:

  • Создайте объект CloseableHttpClient или объект CloseableHttpAsyncClient, первый из которых является синхронным, а второй — асинхронным.
  • Создать объект HTTP-запроса
  • Вызовите метод execute для выполнения запроса. Если это асинхронный запрос, вызовите метод запуска перед его выполнением.

Создайте соединение:

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

Соединение является синхронным соединением

ПОЛУЧИТЬ запрос:

@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.

ПОСТАВИТЬ запрос:

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

Почтовый запрос:

  • добавить объект
    @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

УДАЛИТЬ запрос:

@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
  • Создать объект запроса
  • Инкапсулируйте объект запроса как вызов
  • Выполнять синхронные или асинхронные запросы через Call, вызывать метод execute для синхронного выполнения и вызывать метод постановки в очередь для асинхронного выполнения.

Создайте соединение:

private OkHttpClient client = new OkHttpClient();

ПОЛУЧИТЬ запрос:

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

ПОСТАВИТЬ запрос:

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

Почтовый запрос:

  • добавить объект

    @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.

УДАЛИТЬ запрос:

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

Вызовите метод отмены, чтобы отменить Результаты теста:

task canceled
cost 9110 msc

java.net.SocketException: socket closed...【省略】
резюме
  • OkHttp использует режим сборки для более лаконичного создания объектов и использует методы .post/.delete/.put/.get для представления типа запроса. Нет необходимости создавать HttpGet, HttpPost и другие методы, такие как HttpClient, для создания запроса. тип.
  • В пакете зависимостей, если HttpClient необходимо отправлять асинхронные запросы и реализовывать загрузку файлов, необходимо ввести дополнительные зависимости асинхронных запросов.
     <!---文件上传-->
     <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>
    
  • Отмена запроса, HttpClient использует метод прерывания, OkHttp использует метод отмены, которые достаточно просты.Если используется асинхронный клиент, метод отмены запроса может быть вызван при возникновении исключения.

установка времени ожидания

Настройки времени ожидания HttpClient:
В HttpClient версии 4.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();

резюме:
Если клиент находится в одноэлементном режиме, HttpClient более гибко устанавливает время ожидания, и для разных типов запросов устанавливаются разные значения времени ожидания.Как только OkHttp устанавливает время ожидания, определяется время ожидания всех типов запросов.

Сравнение производительности HttpClient и OkHttp

тестовая среда:

  • Процессор шесть ядер
  • Память 8G
  • windows10

Каждый тестовый пример проверяется пять раз, чтобы исключить случайность

Клиентское соединение является одноэлементным:

Клиентское соединение не является одноточечным:
В одноэлементном режиме скорость отклика HttpClient выше, единица измерения — миллисекунды, и разница в производительности не сильно отличается. В несинглтонном режиме OkHttp имеет лучшую производительность, а HttpClient требует больше времени для создания соединения, потому что в большинстве случаев эти ресурсы будут писаться в одноэлементном режиме, поэтому результаты тестов на рис. 1 более ценны для справки.

Суммировать

OkHttp и HttpClient в производительности и использованииравномерно подобранный, вы можете выбрать в соответствии с фактическим бизнесом
Наконец прикрепил:образец кода,Добро пожаловатьforkиstar*
Прошло много времени с тех пор, как я опубликовал статью.

В основном из-за того, что никто не читал первые две статьи, которые я написал, я был поражен, и мне срочно нужно подтверждение пользователей сети.Нравится