Извините за задержку выпуска версии 1.4.0 из-за большого количества новых функций.
dataType
установлено как "auto"
, что позволяет автоматически распознавать тип возвращаемых данных и декодировать ихRetryer
для расширения стратегий повторной попытки, а также возможность указания через свойство retryer
@Get
, @GetRequest
, @Post
, @PostRequest
, @Delete
, @DeleteRequest
для упрощения описания конечных точек запросов@Query
, @Body
, @Header
. В отличие от предыдущих аннотаций @DataParam
, @DataObject
, эти аннотации имеют более четкое назначениеaddBody
, replaceBody
, getArguments
в ForestRequest
новая функциональность: Загрузка файла без необходимости указания Content-Type
новая функциональность: Аннотация Header
для параметров
новая функциональность: Возможность отправки BODY
информации вместе с GET
запросом (работает только с backend Httpclient
)
новая функциональность: Добавлена аннотация userAgent
##### Исправленные ошибки:
fix: Устранено отсутствие значения url
в аннотации Request
fix: Отсутствие http://
в baseURL
fix: Автоматическое удаление /
из baseUrl
fix: Ошибка сервера 500 при загрузке файла с backend HttpClient
fix: Отсутствие значений для свойств contentType
, contentEncoding
, userAgent
fix: Проблема приоритета между Content-Type
и Content-Encoding
fix: Отсутствие зависимости spring-boot-starter
fix: Отсутствие значения Content-Encoding
в заголовках ответа
fix: Проблема сериализации Map
с помощью FastJSON
fix: Вывод содержимого BODY
запроса GET
в HttpClient
fix: Поддержка последовательности в FastJsonConverter
fix: Отсутствие действия заголовка Content-Type
fix: Отсутствие действия последовательности при преобразовании FastJson
в Map
MethodAnnotationLifeCycle
и ParameterAnnotationLifeCycle
перемещены в другой пакетrefactor: Удалён метод setArguments
из ForestRequest
refactor: Переименовано поле type
в target
в классе MappingParameter
refactor: Удалено поле query
из MappingParameter
, заменено на type
refactor: Единая система сборки URL для Httpclient
refactor: Поле value
в аннотациях Query
, Body
, Header
больше не обязательно заполнять, могут применяться к объектным параметрам
refactor: Обёртка Entity
для методов Get
, Head
, Options
, Trace
, Delete
в Httpclient
Улучшение: Обёртка методов Get
, Head
, Options
, Trace
, Delete
HTTP клиента в Entity
Улучшение: В запросе Query
значение value
не обязательно заполнять, можно использовать для модификации объектных параметров
Улучшение: Удалены аннотации BodyObject
и HeaderObject
Улучшение: Все встроенные аннотации реализуются через расширенный способ
Версия v1.4.0-RC4
выпущена, в которой добавлены аннотации @Get
, @GetRequest
, @Post
, @PostRequest
. Теперь нет необходимости указывать свойство type
в аннотации @Request
.
@Post(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String sendPost1();
@PostRequest(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String sendPost2();
@Get
, @GetRequest
, @Post
, @PostRequest
Content-Encoding
теперь пустая строка;charset=
в заголовках ответа Content-Type
DataQuery
переименован в Query
, DataBody
переименован в Body
версия v1.4.0-RC2
является промежуточной версией, следующая за ней будет уже стабильной. В этой версии были введены аннотации @DataQuery
и @DataBody
, позволяющие устанавливать тип запроса по префиксу имени метода, а также возможность получения заголовков из объекта ForestResponse
.
@DataQuery
и @DataBody
@Request(
url = "http://localhost:${port}/hello/user"
)
String send(@DataQuery("username") String username);
Аннотация @DataQuery
используется для параметров, которые должны быть переданы как часть URL запроса.
@Request(
url = "http://localhost:${port}/complex",
type = "post",
headers = {"Accept:text/plan"}
)
String send(@DataQuery("param") String param,
@DataBody("username") String username,
@DataBody("password") String password);
Аннотация @DataBody
используется для параметров, которые будут отправлены в теле запроса. Исключение составляют методы типа GET
или HEAD
, которые не содержат тела запроса.
@Request(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String getHello(); // GET запрос
@Request(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String postHello(); // POST запрос
@Request(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String putHello(); // PUT запрос
@Request(
url = "http://localhost:${port}/hello",
data = "username=foo&password=123456"
)
String hello(); // Если ни один из префиксов не совпадает и тип запроса не указан, то это GET запрос
feat: По умолчанию имя файла для скачивания берется из URL
feat: Добавление аннотаций @DataQuery и @DataBody
feat: #I1QY77### Исправленные проблемы:
fix: Ошибка при возврате байтового массива после скачивания файла
fix: Переменная [method], которая может быть null или была проверена ранее, но её значение не гарантировано, что вызывает риск возникновения NullPointerException
fix: Переместите этот вызов wait()
в блок синхронизации, чтобы убедиться, что монитор this
был захвачен.
refactor: Удаление внутреннего класса SavingTrustManager, который не использовался
refactor: Замена заголовков запроса на класс ForestHeaderMap
add: Классы ForestHeader и ForestHeaderMap
add: Класс NameUtils для работы с именами
add: Инструмент для вывода прогресса загрузки файла
Версия 1.4.0-RC1
выпущена с новыми возможностями отслеживания прогресса загрузки файлов и механизма повторной попытки.
@Request(url = "http://forspeed.onlinedown.net/down/QQliveSetup_20_731.exe")
@DownloadFile(dir = "${dir}", filename = "${filename}")
File downloadFile(@DataVariable("dir") String dir, @DataVariable("filename") String filename, OnProgress onProgress);
При вызове используется lambda
.
File file = downloadClient.downloadFile("D:\\TestDownload", "QQliveSetup_20_731.exe", progress -> {
System.out.println("------------------------------------------");
System.out.println("Общий размер байт: " + progress.getTotalBytes()); // Размер файла
System.out.println("Текущий размер байт: " + progress.getCurrentBytes()); // Количество загруженных байтов
System.out.println("Процент загрузки: " + Math.round(progress.getRate() * 100) + "%"); // Процент загрузки
if (progress.isDone()) { // Загрузка завершена?
System.out.println("--------Загрузка завершена!--------");
}
});
```#### Механизм повторной попытки:
Добавьте в конфигурационный файл следующее:
```yaml
forest:
retry-count: 3 # Количество повторных попыток при ошибке запроса
max-retry-interval: 2000 # Максимальный интервал времени между повторными попытками, миллисекунды
Если вы хотите указать конкретные настройки повторной попытки для одного запроса, используйте аннотацию @Request
:
@Request(
url = "http://localhost:${port}/hello/user?username=foo",
retryCount = 3,
maxRetryInterval = 2000)
String testRetry();
По умолчанию используется стратегия повторной попытки с использованием алгоритма экспоненциального затухания. Это значит, что вместо того чтобы просто повторять запрос несколько раз, каждая последующая попытка будет осуществляться через увеличивающийся интервал времени, который равен степени двойки от номера попытки. Однако максимальный интервал времени не может превышать значение атрибута maxRetryInterval
.#### Новые возможности:
OnMethodInvoke
в интерцепторахaddAttribute
в интерцепторахaddInterceptorAttribute
класса RequestForestEncoder
, переименование методов convertToJson
и converterToXml
в encodeToString
DEFAULT_CHARSET
@DownloadFile
в пакет extensionsBasicAuthInterceptor
в пакет extension@BasicAuth
в пакет extensionOkHttp
toString
и equals
в динамически проксируемых классах для интерфейса ClientFuture
\
версия v1.4.0-BETA2
была выпущена; в этом выпуске были внесены значительные изменения, но основной акцент сделан на добавлении трёх новых функциональностей: загрузка файлов, пользовательские аннотации-интерцепторы и автоматическое распознавание типов данных.
/**
* Используйте аннотацию @DownloadFile для загрузки файла, атрибут dir указывает целевой каталог, а filename — имя целевого файла
*/
@Request(url = "http://localhost:8080/images/test-img.jpg")
@DownloadFile(dir = "${targetDir}", filename = "new-img.jpg")
void downloadImage(@DataVariable("targetDir") String targetDir);
/**
* Возвращаемый тип — это массив байтов, который позволяет преобразовать загруженный файл в массив байтов
* @return
*/
@Request(url = "http://localhost:8080/images/test-img.jpg")
byte[] downloadImageToByteArray();
/**
* Возвращаемый тип — это InputStream, который позволяет преобразовать загруженный файл в поток, и может использоваться вместе с аннотацией @DownloadFile
* @return
*/
@Request(url = "http://localhost:8080/images/test-img.jpg")
@DownloadFile(dir = "D:\\TestDownload", filename = "temp.jpg")
InputStream downloadImageToInputStream();
MyAuthInceptor
.@InterceptorClass
, указав нужный интерцептор.@Documented
// Метка для интерцептора и указание класса BasicAuthInterceptor
@InterceptorClass(BasicAuthInterceptor.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAuth {
/**
* Имя пользователя для проверки.
*
* @return Имя пользователя.
*/
String username();
}
``` /**
* пароль для проверки
* @return
*/
String password();
}
@BaseRequest(baseURL = "http://localhost:${port}")
@MyAuth(username = "${username}", password = "bar")
public interface BaseAuthClient { ... }
или привязывайте его к методу
@Request(url = "http://localhost:${port}/hello/user?username=${username}")
@MyAuth(username = "${username}", password = "bar")
String send(@DataVariable("username") String username);
Forest в этой версии имеет встроенную базовую аннотацию авторизации @BasicAuth
.
Добавлен тип данных auto
для dataType
, который позволяет автоматически определять формат возвращаемых данных (JSON, XML или TEXT) и производить десериализацию.
@Request(
url = "http://ditu.amap.com/service/regeo",
dataType = "auto" // Автоматическое определение типа данных JSON или XML
)
Map<String, Object> getLocation(@DataParam("longitude") String longitude, @DataParam("latitude") String latitude);
Теперь auto
является значением по умолчанию для типа данных, поэтому вам больше не нужно беспокоиться о том, чтобы заполнять свойство dataType
. Вы можете просто его пропустить.
// В случае отсутствия значения dataType, будет автоматически определён тип данных
@Request(url = "http://ditu.amap.com/service/regeo")
Map<String, Object> getLocation(@DataParam("longitude") String longitude, @DataParam("latitude") String latitude);
feat: Расширенные пользовательские аннотации с привязкой к интерцепторам, создающие метки для интерцепторов
feat: Возможность добавления прикрепленных файлов к объекту ForestRequest
feat: Обработка двоичных данных для преобразования массивов байтов и потоковых типов
feat: Базовая проверка
feat: По умолчанию значение dataType
равно "auto"
, что позволяет автоматически распознавать тип возвращаемых данных#### Устранённые ошибки:
fix: Ошибочный парсинг при встрече символов \
в шаблонной строке
fix: Проблемы совместимости различных версий OkHttp3
fix: Ошибки конвертации данных при использовании Future
в OkHttp
backend
auto
filename
, contentType
, contentEncoding
, contentLength
в классе ForestResponse
InterceptorAttributes
handleInvokeMethod
Interceptor
: beforeExecute
, afterExecute
, addAttribute
, getAttributes
, getAttributeAsString
, getAttributeAsInteger
, getAttributeAsFloat
, getAttributeAsDouble
Base64
@DownloadFile
auto
, binary
ForestResponse
ReflectUtil
в ReflectUtils
ForestConverter
* обновление: регистрация текстовых конвертировщиков, бинарных конвертировщиков и автоматических типовых конвертировщиков в ForestConfiguration
v1.4.0-BETA1
является бета-версией, в которой реализовано основное свойство — загрузка файлов. Возможность загрузки файлов будет доступна в последующих версиях.
@Request(
url = "/upload",
type = "POST",
dataType = "JSON",
contentType = "multipart/form-data"
)
Map upload(@DataFile("file") File file, OnProgress onProgress);
Ключевые моменты:
Используйте аннотацию @DataFile
для параметров, которые требуется загрузить. Поддерживаемые типы данных включают File
, String
, InputStream
, byte[]
, MultipartFile
, Resource
.
Обязательным атрибутом аннотации @DataFile
является value
, которое представляет собой имя параметра запроса для объекта файла.
Атрибут fileName
аннотации @DataFile
представляет имя файла. Для типов данных File
, String
, MultipartFile
, Resource
это необязательное поле, а для InputStream
и byte[]
— обязательное.
Параметр OnProgress
используется для отслеживания прогресса загрузки.
feat: Отслеживание прогресса загрузки файлов
feat: Добавлена аннотация @DataFile
для модификации параметров загрузки файлов, поддерживаются типы данных File
, String
, InputStream
, byte[]
, MultipartFile
, Resource
feat: Добавлен метод обратного вызова OnProgress
для отслеживания прогресса загрузки
feat: Добавлен объект параметра ForestProgress
для метода обратного вызова OnProgress
feat: В аннотации @Request
добавлен атрибут progressStep
, который описывает количество байтов, после которых происходит отслеживание прогресса
feat: В интерфейсе Interceptor
добавлен метод OnProgress
(не обязательно реализуется в реализующем классе)#### Изменения:
refactor: Класс ResponseHandler
переименован в LifeCycleHandler
refactor: Обновлено до версии HttpClient 4.5.2
refactor: Добавлен класс ForestMultipart
, который использует типы данных для загрузки файлов
@DataObject
для параметра типа List
ForestResponse
в качестве типа возвращаемого значенияgetResult
возвращает неверные данныеOnSuccess
callback функция принимает данные с типами параметров generics для парсинга в JSON
с ошибкамиspring boot
okhttp3
okhttp3
Новые возможности в версии v1.3.0:
@BaseRequest
: baseURL
, contentType
, contentEncoding
, timeout
, interceptor
.@BaseURL
больше не рекомендовано.forest.enabled
.Исправленные ошибки:
Изменения:
fix: #I1VJ19