HttpUtils — это набор инструментов для работы с HTTP, основанный на библиотеке OkHttp. Он предоставляет следующие возможности:
<dependency>
<groupId>com.ejlchina</groupId>
<artifactId>httputils</artifactId>
<version>2.1.0</version>
</dependency>
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**
Только асинхронные запросы могут устанавливать функции обратного вызова:
http.async("http://api.demo.com/users/1")
.setOnResponse((HttpResult result) -> {
// Ответный обратный вызов
})
.setOnException((Exception e) -> {
// Обратный вызов исключения
})
.setOnComplete((State state) -> {
// Завершающий обратный вызов, выполняется независимо от успеха или неудачи
})
.get();
Все методы синхронного запроса возвращают объект HttpResult, все методы асинхронного запроса возвращают объект HttpCall.
Объект 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();
Объект 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
Метод sync
и async
объекта HTTP
возвращает объект HttpTask
, который предоставляет ряд методов addXXX
и setXXX
, которые можно использовать для создания цепочки задач.
Однократное добавление (синхронное и асинхронное добавление одинаково):
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();
Параметры пути используются для замены заполнителей в строке 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 )