1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/troyzhxu-httputils

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README-2.1.0.md 23 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 02:06 bb668ec

HttpUtils

Введение

HttpUtils — это набор инструментов для работы с HTTP, основанный на библиотеке OkHttp. Он предоставляет следующие возможности:

  • Поддержка асинхронных и синхронных запросов.
  • Поддержка RESTful-стиля.
  • Автоматическое кодирование и декодирование JSON.
  • TCP-пул соединений.
  • Перехватчики запросов.
  • HTTP/2.
  • Конфигурация потоков обратного вызова.
  • Асинхронные предварительные обработчики.
  • Методы GET, POST, PUT и DELETE.
  • Загрузка и скачивание файлов.

Зависимости

  • OkHttp — основная зависимость, которая использует пакет Okio в качестве зависимости нижнего уровня.
  • Fastjson — библиотека для быстрого анализа JSON от Alibaba.

Контакты

Текущая версия документа 2.1.0

Для просмотра версии 2.0.0 нажмите здесь. | Для просмотра версий 1.x.x нажмите здесь.

Установка

Maven

<dependency>
     <groupId>com.ejlchina</groupId>
     <artifactId>httputils</artifactId>
     <version>2.1.0</version>
</dependency>

Gradle

compile 'com.ejlchina:httputils:2.1.0'

Использование

HttpCall call = http.async("http://api.demo.com/users/1") .addJsonParam("name", "Jack") .setOnResponse((HttpResult result) -> {

})
.put();                                                         // **Асинхронный PUT**
**2.4 DELETE**

```java
HttpResult result = http.sync("http://api.demo.com/users/1").delete();  // **Синхронный DELETE**

HttpCall call = http.async("http://api.demo.com/users/1")
    .setOnResponse((HttpResult result) -> {
        
    })
    .delete();                                                      // **Асинхронный DELETE**

3 Анализ и выполнение результатов

3.1 Функции обратного вызова

Только асинхронные запросы могут устанавливать функции обратного вызова:

http.async("http://api.demo.com/users/1")
    .setOnResponse((HttpResult result) -> {
        // Ответный обратный вызов
    })
    .setOnException((Exception e) -> {
        // Обратный вызов исключения
    })
    .setOnComplete((State state) -> {
        // Завершающий обратный вызов, выполняется независимо от успеха или неудачи
    })
    .get();

Все методы синхронного запроса возвращают объект HttpResult, все методы асинхронного запроса возвращают объект HttpCall.

3.2 HttpResult

Объект HttpResult представляет собой результат выполнения HTTP-запроса после его завершения. Он является возвращаемым значением методов синхронного запроса (get, post, put, delete) и параметром обратного вызова ответа (OnResponse) для асинхронных запросов. У него есть следующие методы:

  • getState() — получение статуса выполнения запроса в виде перечисления, которое может принимать следующие значения:
    • State.CANCELED — запрос отменён;
    • State.RESPONDED — получен ответ;
    • State.TIMEOUT — истекло время ожидания запроса;
    • State.NETWORK_ERROR — ошибка сети;
    • State.EXCEPTION — другое исключение запроса.
  • getStatus() — получение кода состояния HTTP.
  • isSuccessful() — проверка успешности ответа, код состояния находится в диапазоне [200..300).
  • getHeaders() — получение заголовков HTTP-ответа.
  • getBody() — получение тела ответа. Этот метод имеет следующие подметоды:
    • toBytes() — возвращает массив байтов;
    • toByteStream() — возвращает поток байтов;
    • toCharStream() — возвращает символьный поток;
    • toString() — возвращает строку;
    • toJsonObject() — преобразует в объект Json;
    • toJsonArray() — преобразует в массив Json;
    • toBean(Class<T> type) — преобразует в JavaBean на основе типа;
    • toBean(TypeReference<T> type) — преобразует в JavaBean на основе ссылки на тип;
    • toFile(String filePath) — загружает файл в указанный каталог и возвращает сохранённый файл;
    • toFile(File file) — загружает файл и сохраняет его в указанном файле;
    • getContentType() — получает тип содержимого тела сообщения;
    • getContentLength() — получает длину тела сообщения в байтах.
    • Для одного и того же объекта Body методы toXXX() можно использовать только один раз.
  • getError() — исключение, возникшее во время выполнения, автоматически перехватывает ошибки тайм-аута сети, сетевые ошибки и другие исключения запросов.

Например, загрузка файла в указанный каталог:

String path = "D:/reports/2020-03-01.xlsx"; // Каталог сохранения файлов

// Синхронная загрузка
http.sync("http://api.demo.com/reports/2020-03-01.xlsx")
    .get().getBody().toFile(path);

// Асинхронная загрузка
http.async("http://api.demo.com/reports/2020-03-01.xlsx")
    .setOnResponse((HttpResult result) -> {
        result.getBody().toFile(path);
    })
    .get();

3.3 HttpCall

Объект HttpCall является результатом асинхронного метода запроса (get, post, put, delete), он похож на интерфейс Future в Java. У него есть следующие методы:

  • cancel() — отменяет текущий запрос и возвращает результат отмены.
  • isCanceled() — проверяет, был ли запрос отменён.
  • isDone() — проверяет, выполнен ли запрос, включая отмену и неудачу.
  • getResult() — возвращает объект HttpResult, представляющий результат выполнения запроса, если запрос не завершён, то текущий поток будет приостановлен до завершения выполнения.

Пример отмены асинхронного запроса:

HttpCall call = http.async("http://api.demo.com/users/1").get();

System.out.println(call.isCanceled());   // false

boolean success = call.cancel();   // Отмена запроса

System.out.println(success);             // true
System.out.println(call.isCanceled());   // true

4 Создание HTTP-задачи

Метод sync и async объекта HTTP возвращает объект HttpTask, который предоставляет ряд методов addXXX и setXXX, которые можно использовать для создания цепочки задач.

4.1 Добавление заголовков запросов

Однократное добавление (синхронное и асинхронное добавление одинаково):

http.sync("http://api.demo.com/orders")
    .addHeader("Token", "xxxxxx")
    .addHeader("Accept", "application/json")
    .get();

Добавление нескольких заголовков (синхронное и асинхронное добавление одинаково):

Map<String, String> headers = new HashMap<>()
headers.put("Token", "xxxxxx");
headers.put("Accept", "application/json");

http.sync("http://api.demo.com/orders")
    .addHeader(headers)
    .get();

4.2 Добавление параметров пути

Параметры пути используются для замены заполнителей в строке URL.

Однократное добавление (синхронное и асинхронное добавление одинаково):

http.sync("http://api.demo.com/shops/{shopName}/products/{productId}")
    .addPathParam("shopName", "taobao")
    .addPathParam("productId", 20)
    .get();

Добавление нескольких параметров (синхронное и асинхронное добавление одинаково):

Map<String, String> params = new HashMap<>()
params.put("shopName", "taobao");
params.put("productId", 20);
``` **Добавление параметров в запросы**

В запросах могут использоваться различные параметры, которые добавляются к URL разными способами.

1. **Параметры запроса (URL-параметры)** используются для добавления параметров после строки запроса URL. Они могут быть добавлены как синхронно, так и асинхронно:

    * Синхронное добавление:

        ```java
        http.sync("http://api.demo.com/shops/{shopName}/products/{productId}")
                .addPathParam(params)
                .get();
        ```

    * Асинхронное добавление: аналогично.

2. **Параметры формы (Body-параметры)** передаются с запросом в теле сообщения. Они также могут быть добавлены синхронно или асинхронно:

     * Синхронное добавление:

         ```java
         http.sync("http://api.demo.com/signin")
                 .addBodyParam("username", "Jackson")
                 .addBodyParam("password", "xxxxxx")
                 .post();
         ```

     ```java
     Map<String, String> params = new HashMap<>();
     params.put("username", "Jackson");
     params.put("password", "xxxxxx");

     http.sync("http://api.demo.com/signin")
             .addBodyParam(params)
             .post();
         ```

3. **JSON-параметры** передаются в виде строки JSON в теле запроса. Их можно добавить синхронно или асинхронно:

      * Синхронное добавление:

          ```java
          http.sync("http://api.demo.com/signin")
                  .addJsonParam("username", "Jackson")
                  .addJsonParam("password", "xxxxxx")
                  .post();
          ```

       ```java
       Map<String, Object> params = new HashMap<>();
       params.put("username", "Jackson");
       params.put("password", "xxxxxx");

       http.sync("http://api.demo.com/signin")
               .addJsonParam(params)
               .post();
           ```

4. **Установка JSON-строки**:

      ```java
      http.sync("http://api.demo.com/signin")
              .setRequestJson("\"username\":\"Jackson\",\"password\":\"xxxxxx\"")
              .post();
      ```

5. **Преобразование JavaBean в JSON**:

      ```java
      Login login = new Login();
      login.setUsername("Jackson");
      login.setPassword("xxxxxx");

      http.sync("http://api.demo.com/signin")
              .setRequestJson(login)
              .post();
      ```

6. **Файл-параметры**:

   * **Загрузка локальных файлов**:

       ```java
       File file1 = new File("D:/1.jpg");
       File file2 = new File("D:/2.jpg");

       http.sync("http://api.demo.com/upload")
               .addFileParam("image1", file1)
               .addFileParam("image2", file2)
               .post();
       ```

   * **Использование потока ввода файла**:

       ```java
       // Получение потока ввода файла
       InputStream input = ...

       http.sync("http://api.demo.com/upload")
               .addFileParam("image", "jpg", input)
               .post();
       ```

   * **Использование массива байтов файла**:

       ```java
       // Получение массива байтов файла
       byte[] content = ...

       http.sync("http://api.demo.com/upload")
               .addFileParam("image", "jpg", content)
               .post();
       ```

7. **Совместное использование параметров формы и файл-параметров**:

    ```java
    File file = new File("D:/首页广告.jpg");

    http.sync("http://api.demo.com/messages")
            .addBodyParam("name", "广告图")
            .addFileParam("image", file)
            .post();
    ```

8. **Метки**:

    Иногда необходимо классифицировать HTTP-задачи. Для этого используются метки:

    ```java
    http.async("http://api.demo.com/users")     //(1)
            .setTag("A")
            .get();

    http.async("http://api.demo.com/users")     //(2)
            .setTag("A.B")
            .get();

    http.async("http://api.demo.com/users")     //(3)
            .setTag("B")
            .get();

    http.async("http://api.demo.com/users")     //(4)
            .setTag("B.C")
            .get();

    http.async("http://api.demo.com/users")     //(5)
            .setTag("C")
            .get();
    ```

9. **Отмена задач по меткам**:

    Только асинхронные задачи могут быть отменены. Метка может использоваться не только для отмены задач, но и в препроцессорах. **Как изменить поток выполнения обратного вызова функции и как настроить обратный вызов-исполнитель**

Чтобы изменить поток выполнения для обратного вызова функции, можно настроить обратный вызов-исполнитель. Например, в Android, чтобы все обратные вызовы выполнялись в потоке пользовательского интерфейса (UI), можно выполнить следующую конфигурацию при создании HTTP:
```java
HTTP http = HTTP.builder()
        .callbackExecutor((Runnable run) -> {
            runOnUiThread(run);             // Выполнить в UI потоке
        })
        .build();

Эта конфигурация влияет на обратные вызовы OnResponse, OnException и OnComplete.

Конфигурация OkHttpClient

В отличие от других оболочек OkHttp, HttpUtils не скрывает полезные функции самого OkHttp. Можно выполнить следующие настройки:

HTTP http = HTTP.builder()
    .config((Builder builder) -> {
        // Настройка пула соединений: минимум 10 соединений (по умолчанию 5)
        builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES));
        // Настройка времени ожидания соединения
        builder.connectTimeout(20, TimeUnit.SECONDS);
        // Добавление перехватчика
        builder.addInterceptor((Chain chain) -> {
            Request request = chain.request();
            // Необходимо вернуть результат синхронно, перехватчики не могут выполнять асинхронные операции
            return chain.proceed(request);
        });
        // Другие настройки: SSL, кэш, прокси, события и т.д.
    })
    .build();

Параллельный препроцессор

Препроцессор (Preprocessor) позволяет нам изменять запросы перед их отправкой, но в отличие от перехватчиков (Interceptor) OkHttp, препроцессоры позволяют нам обрабатывать эти изменения асинхронно.

Например, если мы хотим автоматически добавлять токен заголовка к запросам, а токен можно получить только асинхронным методом requestToken, то использование перехватчика может быть затруднительным. Однако мы можем легко решить эту проблему с помощью препроцессора:

HTTP http = HTTP.builder()
        .addPreprocessor((Process process) -> {
            HttpTask<?> task = process.getTask();       // Получить текущую задачу HTTP
            if (!task.tagMatched("Auth")) {             // Проверить, нужна ли задача токена
                return;
            }
            requestToken((String token) -> {            // Асинхронное получение токена
                task.addHeader("Token", token);         // Добавить токен в заголовок задачи
                process.proceed();                      // Продолжить текущую задачу
            }); 
        })
        .build();

Как и перехватчики, препроцессоры также можно добавить несколько.

Последовательный препроцессор

Обычные препроцессоры могут работать параллельно, но иногда мы хотим, чтобы один препроцессор обрабатывал только одну задачу за раз. Например, когда токен истекает, мы должны обновить его, и эта операция должна выполняться только одной задачей за раз, потому что если несколько задач попытаются обновить токен одновременно, некоторые из них могут получить уже недействительный токен. Это нежелательно.

Для решения этой проблемы HttpUtils предоставляет последовательный препроцессор, который позволяет задачам входить в препроцессор по очереди:

HTTP http = HTTP.builder()
        .addSerialPreprocessor((Process process) -> {
            HttpTask<?> task = process.getTask();       // Получить текущую задачу HTTP
            if (!task.tagMatched("Auth")) {             // Проверить, нужна ли задаче токен
                return;
            }
            // Проверить срок действия, обновить при необходимости
            requestTokenAndRefreshIfExpired((String token) -> {
                task.addHeader("Token", token);         // Добавить токен в заголовок задачи
                process.proceed();                      // Вызов этого метода не позволит другим задачам войти в этот обработчик
            }); 
        })
        .build();

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

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/troyzhxu-httputils.git
git@api.gitlife.ru:oschina-mirror/troyzhxu-httputils.git
oschina-mirror
troyzhxu-httputils
troyzhxu-httputils
master