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

OSCHINA-MIRROR/troyzhxu-httputils

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

HttpUtils

Maven Central License Troy.Zhou

自 v2.3.0 后更名为 OkHttps 点我跳转

本仓库已不再更新维护!!!

HttpUtils 的功能,OkHttps 都有,并且更加强大,推荐请使用 OkHttps!

新仓库地址:https://gitee.com/ejlchina-zhxu/okhttps

文档:http://okhttps.ejlchina.com/

介绍

  HttpUtils 是近期开源的对 OkHttp 轻量封装的框架,它独创的异步预处理器,特色的标签,灵活的上传下载进度监听与过程控制功能,在轻松解决很多原本另人头疼问题的同时,设计上也力求纯粹与优雅。

  • 链式调用,一点到底
  • BaseURL、URL占位符、JSON自动封装与解析
  • 同步拦截器、异步预处理器、回调执行器
  • 文件上传下载(过程控制、进度监听)
  • TCP连接池、Http2

当前文档版本[2.3.0]

查阅[2.1.x]点我 | 查阅[2.0.x]点我 | 查阅[1.0.x]点我

目录

安装教程

Maven

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

Gradle

compile 'com.ejlchina:httputils:2.3.0'

使用说明

1 简单示例

1.1 构建 HTTP

HTTP http = HTTP.builder().build();

  以上代码构建了一个最简单的HTTP实例,它拥有以下三个方法:

  • async(String url) 开始一个异步HTTP任务
  • sync(String url) 开始一个同步HTTP任务
  • cancel(String tag) 根据标签批量取消HTTP任务

  为了使用方便,在构建的时候,我们更愿意指定一个BaseUrl(请参见5.1 设置 BaseUrl):

HTTP http = HTTP.builder()
        .baseUrl("http://api.demo.com")
        .build();

  为了简化文档,下文中出现的http均是在构建时设置了BaseUrlHTTP实例。

1.2 同步请求

  使用方法sync(String url)开始一个同步请求:

List<User> users = http.sync("/users") // http://api.demo.com/users
        .get()                         // GET请求
        .getBody()                     // 获取响应报文体
        .toList(User.class);           // 得到目标数据

  方法sync返回一个同步HttpTask,可链式使用。

1.3 异步请求

  使用方法async(String url)开始一个异步请求:

http.async("/users/1")                //  http://api.demo.com/users/1
        .setOnResponse((HttpResult result) -> {
            // 得到目标数据
            User user = result.getBody().toBean(User.class);
        })
        .get();                       // GET请求

  方法async返回一个异步HttpTask,可链式使用。 Запрос тела в формате JSON или преобразование в JSON JavaBean:

  • setRequestJson(Object bean, String dateFormat) — установка тела запроса в формате JSON либо преобразование в формат JSON JavaBean.

Загрузка файлов:

  • addFileParam(String name, String filePath) — загрузка файла;
  • addFileParam(String name, File file) — загрузка файла;
  • addFileParam(String name, InputStream inputStream) — загрузка файла;
  • addFileParam(String name, String type, InputStream input) — загрузка файла;
  • addFileParam(String name, byte[] content) — загрузка файла.

Добавление тегов:

  • setTag(String tag) — добавление тега к HTTP-задаче.

Установка диапазона:

  • setRange(long rangeStart) — настройка Range-заголовка для использования при частичной передаче данных;
  • setRange(long rangeStart, long rangeEnd) — настройка Range-заголовка для использования при блочной загрузке данных.

Привязка объекта:

  • bind(Object object) — привязка объекта, который может быть использован для реализации жизненного цикла привязки в Android.

5. Использование тегов

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

http.async("/users")    // (1)
        .setTag("A").get();

http.async("/users")    // (2)
        .setTag("A.B").get();

http.async("/users")    // (3)
        .setTag("B").get();

http.async("/users")    // (4)
        .setTag("B.C").get();

http.async("/users")    // (5)
        .setTag("C").get();

После добавления тегов можно отменять задачи по тегам:

int count = http.cancel("B");              // (2), (3), (4) будут отменены (отменяются задачи с тегом «B»)
System.out.println(count);                 // вывод 3

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

6. Настройка HTTP

6.1. Установка BaseUrl

HTTP http = HTTP.builder()
        .baseUrl("http://api.demo.com")    // установка BaseUrl
        .build();

Эта конфигурация действует глобально. После настройки BaseUrl конкретные запросы могут быть опущены, что делает код более лаконичным:

http.sync("/users").get()                  // http://api.demo.com/users

http.sync("/auth/signin")                  // http://api.demo.com/auth/signin
        .addBodyParam("username", "Jackson")
        .addBodyParam("password", "xxxxxx")
        .post()                            // POST-запрос

Если есть специальные задачи, всё ещё можно использовать полный путь, это не помешает:

http.sync("https://www.baidu.com").get()

6.2. Обработчик обратного вызова

Чтобы изменить поток выполнения функции обратного вызова, можно настроить обработчик обратного вызова. Например, в Android можно выполнить все обратные вызовы в потоке пользовательского интерфейса, настроив следующим образом:

HTTP http = HTTP.builder()
        .callbackExecutor((Runnable run) -> {
            runOnUiThread(run);            // выполнение в потоке UI
        })
        .build();

Этот параметр влияет на все обратные вызовы.

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

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

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

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

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

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

HTTP http = HTTP.builder()
        .addPreprocessor((PreChain chain) -> {
            HttpTask<?> task = chain.getTask();// получение текущей HTTP-задачи
            if (!task.isTagged("Auth")) {      // проверка необходимости Token для этой задачи по метке
                return;
            }
            requestToken((String token) -> {   // асинхронный запрос Token
                task.addHeader("Token", token);// добавление заголовка к задаче
                chain.proceed();               // продолжение текущей задачи
            });
        })
        .build();

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

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

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

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

HTTP http = HTTP.builder()
        .addSerialPreprocessor((PreChain chain) -> {
            HttpTask<?> task = chain.getTask();
            if

Обратите внимание, что данный текст представляет собой машинный перевод и может содержать неточности. (!task.isTagged("Auth")) {
    return;
}
// 检查过期,若需要则刷新Token
requestTokenAndRefreshIfExpired((String token) -> {
    task.addHeader("Token", token);            
    chain.proceed();               // 调用此方法前,不会有其它任务进入该处理器
});
})
.build();

#### 6.6 全局回调处理
```java
HTTP http = HTTP.builder()
        .responseListener((HttpTask<?> task, HttpResult result) -> {
            // 所有请求响应后都会走这里
            
            return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示不再执行
        })
        .completeListener((HttpTask<?> task, State state) -> {
            // 所有请求执行完都会走这里
            
            return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示不再执行
        })
        .exceptionListener((HttpTask<?> task, IOException error) -> {
            // 所有请求发生异常都会走这里
            
            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示不再执行
        })
        .build();

6.7 全局下载监听

HTTP http = HTTP.builder()
        .downloadListener((HttpTask<?> task, Download download) -> {
            // 所有下载在开始之前都会先走这里
            Ctrl ctrl = download.getCtrl();         // 下载控制器
            
        })
        .build();
### 7 使用 HttpUtils 

  `HttpUtils`本是 1.x 版本里的最重要的核心类由于在 2.x 版本里抽象出了`HTTP`接口使得它的重要性已不如往昔但合理的使用它仍然可以带来不少便利特别是在没有IOC容器的环境里比如在Android开发和一些工具项目的开发中

  `HttpUtils`共定义了四个静态方法

* `async(String url)`  开始一个异步请求 内容通过一个`HTTP`单例实现
* `sync(String url)`   开始一个同步请求 内容通过一个`HTTP`单例实现
* `cancel(String tag)` 按标签取消请求内容通过一个`HTTP`单例实现
* `of(HTTP http)`      配置`HttpUtils`持有的`HTTP`实例不调用此方法前默认使用一个没有没有经过任何配置的`HTTP`懒实例

  也就是说能使用`http`实例的地方都可以使用`HttpUtils`例如

```java
// 在配置HTTP实例之前,只能使用全路径方式
List<Role> roles = HttpUtils.sync("http://api.demo.com/roles")
        .get().getBody().toList(Role.class);

// 配置HTTP实例,全局生效
HttpUtils.of(HTTP.builder()
        .baseUrl("http://api.demo.com")
        .build());

// 内部使用新的HTTP实例
List<User> users = HttpUtils.sync("/users")
        .get().getBody().toList(User.class);
### 8 文件下载

  HttpUtils 并没有把文件的下载排除在常规的请求之外同一套API它优雅的设计使得下载与常规请求融合的毫无违和感一个最简单的示例

```java
http.sync("/download/test.zip")
        .get()                           // 使用 GET 方法(其它方法也可以,看服务器支持)
        .getBody()                       // 得到报文体
        .toFile("D:/download/test.zip")  // 指定下载的目录,文件名将根据下载信息自动生成
        .start();                        // 启动下载

  或使用异步连接方式:

http.async("/download/test.zip")
        .setOnResponse((HttpResult result) -> {
            result.getBody().toFile("D:/download/test.zip").start();
        })
        .get();

  这里要说明一下:syncasync的区别在于连接服务器并得到响应这个过程的同步与异步(这个过程的耗时在大文件下载中占比极小),而start方法启动的下载过程则都是异步的。

8.1 下载进度监听

  就直接上代码啦,诸君一看便懂:

http.sync("/download/test.zip")
        .get()
        .getBody()
        .setStepBytes(1024)   // 设置每接收 1024 个字节执行一次进度回调(不设置默认为 8192)  
 //     .setStepRate(0.01)    // 设置每接收 1% 执行一次进度回调(不设置以 StepBytes 为准)  
        .setOnProcess((Process process) -> {           // 下载进度回调
            long doneBytes = process.getDoneBytes();   // 已下载字节数
            long totalBytes = process.getTotalBytes(); // 总共的字节数
            double rate = process.getRate();           // 已下载的比例
            boolean isDone = process.isDone();         // 是否下载完成
        })
        .toFolder("D:/download/")        // 指定下载的目录,文件名将根据下载信息自动生成
 //     .toFile("D:/download/test.zip")  // 指定下载的路径,若文件已存在则覆盖
        .setOnSuccess((File file) -> {   // 下载成功回调
            
        })
        .start();

  值得一提的是:由于 HttpUtils 并没有把下载做的很特别,这里设置的进度回调不只对下载文件起用作,即使对响应JSON的常规请求,只要设置了进度回调,它也会告�ть你报文接收的进度(提前是服务器响应的报文有Content-Length头),例如:

List<User> users = http.sync("/users")
        .get()
        .getBody()
        .setStepBytes(2)
        .setOnProcess((Process process) -> {
            System.out.println(process.getRate());
        })
        .toList(User.class);
#### 8.2 下载过程控制

  过于简单还是直接上代码

```java
Ctrl ctrl = http.sync("/download/test.zip")
        .get() ### 1. Выполнение асинхронного запроса

```java
HttpCall call = http.async("/upload")
        .addFileParam("test", "D:/download/test.zip")
        .setOnProcess((Process process) -> {
            System.out.println(process.getRate());
        })
        .post()

call.cancel();  // 取消上传

Вопрос: «У функции отмены загрузки нет таких опций, как приостановка и возобновление, наверное, никому это не нужно?»

2. Свободное переключение между потоками выполнения (для Android)

В процессе разработки под Android часто требуется выполнять определённый код в отдельном потоке. Например, обновление страницы после сетевого запроса выполняется в основном (UI) потоке, а сохранение файла — в потоке ввода-вывода (IO). HttpUtils предоставляет хорошее решение для подобных задач.

По умолчанию все обратные вызовы выполняются в потоке IO. Почему была выбрана такая реализация? Дело в том, что HttpUtils — это чистый Java-пакет инструментов для работы с HTTP, который не зависит от Android и не знает о специфике его UI-потока. Такой подход расширяет возможности использования пакета за пределами Android.

Однако при использовании HttpUtils в контексте Android возникает вопрос: можно ли элегантно решить проблему с UI-потоком? Конечно, можно! Простой способ — настроить обработчик обратного вызова:

HTTP http = HTTP.builder()
        .callbackExecutor((Runnable run) -> {
            // В реальном коде Handler можно вынести за пределы каждого обратного вызова, чтобы избежать повторного создания
            new Handler(Looper.getMainLooper()).post(run); // Выполнить в главном потоке
        })
        .build();

Приведённый выше код позволяет выполнить все обратные вызовы в основном потоке, например:

http.async("/users")
        .addBodyParam("name", "Jack")
        .setOnProcess((Process process) -> {
            // Выполняется в основном потоке
        })
        .setOnResponse((HttpResult result) -> {
            // Выполняется в основном потоке
        })
        .setOnException((Exception e) -> {
            // Выполняется в основном потоке
        })
        .setOnComplete((State state) -> {
            // Выполняется в основном потоке
        })
        .post();

Но если вы хотите, чтобы некоторые обратные вызовы выполнялись в потоке ввода-вывода, обеспечивая свободное переключение, как это сделать? HttpUtils предлагает гибкий метод:

http.async("/users")
        .addBodyParam("name", "Jack")
        .setOnProcess((Process process) -> {
            // Выполняется в основном потоке
        })
        .nextOnIO()          // Следующий обратный вызов выполняется в потоке ввода-вывода
        .setOnResponse((HttpResult result) -> {
            // Выполняется в потоке ввода-вывода
        })
        .setOnException((Exception e) -> {
            // Если не указано nextOnIO, выполняется в обработчике обратного вызова
            // Здесь выполняется в основном потоке
        })
        .nextOnIO()          // Следующий обратный вызов выполняется в потоке ввода-вывода
        .setOnComplete((State state) -> {
            // Выполняется в потоке ввода-вывода
        })
        .post();

Любой обратный вызов может быть свободно переключён с помощью метода nextOnIO(). То же самое относится и к загрузке файлов:

http.sync("/download/test.zip")
        .get()
        .getBody()
        .setOnProcess((Process process) -> {
            // Выполняется в основном потоке
        })
        .toFolder("D:/download/")
        .nextOnIO()          // Следующий обратный вызов выполняется в потоке ввода-вывода
        .setOnSuccess((File file) -> {
            // Выполняется в потоке ввода-вывода
        })
        .setOnFailure((Failure failure) -> {
            // Выполняется в основном потоке
        })
        .start();

Комментарии ( 0 )

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

Введение

Http-инструментарий: OkHttp — это лёгкая оболочка, предоставляющая широкий спектр функций. Она элегантна и лаконична в дизайне и становится новым выбором для решения Http-проблем как на фронтенде, так и на бэкенде в области Java. Развернуть Свернуть
Apache-2.0
Отмена

Обновления (8)

все

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
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