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

OSCHINA-MIRROR/dromara-forest

11.03.2025 04:23
GitLife Service Account

версия v1.5.20 выпущена. Из-за занятости другими делами работа над ней несколько затянулась, но благодаря поддержке других участников проекта удалось значительно продвинуться в развитии этой версии, особенно в части совместимости с JDK 17. Отдельное спасибо хочется выразить за это. В данной версии основной акцент сделан на поддержку новых версий JDK, включая все версии от 8 до 17 (особенно проверены популярные версии 11 и 17, а версию 8 поддерживают уже давно).

Новые возможности

  • feat: Поддержка JDK 17, совместимость со всеми версиями JDK от 8 до 17

Исправленные проблемы

  • fix: Установка connectTimeout и readTimeout в BaseRequest не работает (#I4Z8Y0)
  • fix: Проблема с переполнением памяти при скачивании (#I4NFPE)
  • fix: Настройка basePath в AddressSource не действует (#I50LVA)

Отдельное спасибо

  • @CHMing
Последнее сообщение коммита: update: 1.5.20
11.03.2025 04:23
GitLife Service Account

v1.5.19 версия выпущена, в этом выпуске были исправлены некоторые ошибки.

Исправленные проблемы:

  • fix: В нативной среде Spring, интерцепторы не могут быть внедрены в контекст Spring (#I4UE9T)

  • fix: При параллельном использовании пула соединений HTTPS в бэкенд-части HttpClient данные смешиваются (#I4TYJ1)

  • fix: При наличии двух заголовков Set-Cookie, можно получить только последний (#I4TATV)

Другие изменения:

  • refactor: Удалена зависимость от пакета commons-logging
Последнее сообщение коммита: update: new version 1.5.19
11.03.2025 04:23
GitLife Service Account

версия v1.5.17 выпущена. В этом выпуске были исправлены ранее существовавшие ошибки, а также добавлена возможность динамического управления источниками прокси.

Новые возможности:

feat: Динамическое управление источниками прокси (#I4SYM1)

Исправленные проблемы:

fix: Исключение: Файл SSL KeyStore пуст (#I4SYGB)
fix: Настройка maxRetryInterval не работает (#I4SV2P)
fix: Ошибка при отсутствии зависимости lang3 в основном проекте (#I4M9DE)
fix: Объединённые аннотации не применяются (#I4N2HC)

Другие изменения:

refactor: Удаление повторяющихся условий if в util-классе NameUtils

Отдельное спасибо:

@CHMing

Последнее сообщение коммита: update: new version 1.5.17
11.03.2025 04:23
GitLife Service Account

1. 5. 15 версия выпущена, в которой добавлены пользовательские SSL-верификаторы доменного имени, а также исправлена проблема с кодировкой символов ответа Response и распаковкой gzip.

Forest принял участие в конкурсе открыток проектов OSC 2021 года. Если вам нравится Forest или вас интересует этот проект, пожалуйста, проголосуйте за него своим голосом. Благодарим!

Проголосовать 👉

Основные изменения

Пользовательский hostnameVerifier

Определите класс, реализующий интерфейс HostnameVerifier

/**
 * Пользовательский SSL-верификатор доменного имени
 */
public class MyHostnameVerifier implements HostnameVerifier {
    @Override
    public boolean verify(String s, SSLSession sslSession) {
        if ("gitee.com".equals(s)) {
            return true;
        }
        return false;
    }
}

Настройте пользовательский SSL-верификатор доменного имени в конфигурационном файле KeyStore Forest

Настройка в файле application.yml Spring Boot проекта

forest:
  ssl-key-stores:
    - id: keystore1
      hostname-verifier: your.site.MyHostnameVerifier

Привязка к методу API

@Post(url = "/something", keyStore = "keystore1")
String postSomething(@Body body);

Аннотация @SSLHostnameVerifier

Кроме глобальной конфигурации в файле keyStore, можно использовать аннотацию для прямой привязки к методу API

public class MyHostnameVerifier implements HostnameVerifier {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        // Пропустить запросы только для домена gitee.com
        if ("gitee.com".equals(hostname)) {
            return true;
        }
        return false;
    }
}
```Привязка через аннотацию `@SSLHostnameVerifier`
```java
@Post(url = "/something")
@SSLHostnameVerifier(TrustAnyHostnameVerifier.class)
String postSomething(@Body body);

Аннотация @SSLSocketFactoryBuilder

Аналогично, можно настроить SSLSocketFactory, используя аннотацию @SSLSocketFactoryBuilder

public class MySSLSocketFactoryBuilder implements SSLSocketFactoryBuilder {
    @Override
    public SSLSocketFactory getSSLSocketFactory(ForestRequest request, String protocol) throws Exception {
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null,
                new TrustManager[]{new TrustAllManager()},
                new SecureRandom());
        System.out.println("do MySSLSocketFactoryBuilder");
        return sslContext.getSocketFactory();
    }
}

Привязка к интерфейсу

@Post(url = "/что-то")
@SSLSocketFactoryBuilder(MySSLSocketFactoryBuilder.class)
String postЧего_то(@Body body);

Обновление

Новые возможности

  • feat: возможность настройки hostnameVerifier и SSLSocketFactoryBuilder (#I4LGW8)
  • feat: автоматическое распознавание gzip-сжатия данных в ответах на основе Content-Encoding и автоматическая декомпрессия

Исправленные проблемы

  • fix: повторное увеличение параметра запроса после переадресации (#I4LPGU)
  • fix: исправление ошибок преобразования символьной кодировки, вызванных content-encoding (#I4LJ3X)
  • fix: исправление ошибок в логике определения символьной кодировки

Изменения кода

  • add: аннотация @SSLHostnameVerifier
  • add: аннотация @SSLSocketFactoryBuilder

Благодарность

Этот выпуск был возможен благодаря вкладу участника @designer, за что мы очень благодарны!## Голосование за проект Forest на конкурсе "Китайская открытая лицензионная программа" 2021 года
Проект Forest участвует в голосовании "Китайской открытой лицензионной программы" 2021 года. Если вам нравится Forest или вас интересует этот проект, пожалуйста, проголосуйте за него своим голосом. Большое спасибо!
Голосовать здесь

Последнее сообщение коммита: feat: #I4LGW8 自定义 hostnameVerifier 和 SSLSocketFactoryBuilder
11.03.2025 04:22
GitLife Service Account

версия v1.5.14 выпущена! В этом выпуске были исправлены проблемы с установкой размера пула асинхронных потоков и анализом символа @ в URL.

Новые возможности

  • feat: поддержка установки размера пула потоков для асинхронных запросов (#I4JXN3)
  • feat: добавление метода получения всех пар ключ-значение для объекта ForestBody (включая объект Body) (#I4JDRR)

Исправленные ошибки

  • fix: удаление символа @ при его наличии в URL (#I4J3LU)

Добавленные элементы кода

  • add: класс AsyncAbortPolicy
  • add: метод ForestBody.nameValuesMapWithObject

Улучшения

  • optimize: процесс анализа аннотации @Backend
Последнее сообщение коммита: add: ForestBody.nameValuesMapWithObject
11.03.2025 04:22
GitLife Service Account

версия v1.5.13 выпущена. В этом выпуске были исправлены некоторые проблемы с парсингом URL и добавлена возможность указывать тип тела запроса и его кодировщик.

Новые возможности

  • feat: Аннотация @BodyType для указания типа тела запроса (#I4IF3N)
  • feat: Метод для получения всех ключей и значений параметров тела запроса (#I4GWO7)

Исправленные ошибки

  • fix: Установка пользовательского кодировщика Encoder в запросе не работает (#I4HNZF)
  • fix: Проблемы с парсингом URL, если он содержит символ @ (#I4GQWW)

Другие изменения

  • add: Аннотация BodyType
  • add: Аннотация FastjsonEncoder
  • add: Аннотация GsonEncoder
  • add: Аннотация JacksonEncoder

Неразрывные изменения

  • delete: Класс com.dtflys.forest.http.ForestBodyType
  • update: Параметр метода setBodyType и bodyType класса ForestRequest изменён на ForestDataType
Последнее сообщение коммита: update: 新版本 1.5.13
11.03.2025 04:22
GitLife Service Account

версия v1.5.12 выпущена. В этом выпуске произошло substantial重构后台,并解决了若干与URL解析相关的问题。

Новые возможности:

  • feat: getbody теперь может использовать ключ-значение для получения значений (#I4FUSB)

Исправление ошибок:

  • fix: повторное закодирование параметров URL (#I4FDJC)
  • fix: ошибка в шаблоне строки с использованием формата {variable name} при ссылке на скрытую переменную (#I4EP04)
  • fix: ошибка парсинга URL в формате http://localhost/xxx:yyy (#I4GC5M)
  • fix: различие в поведении кодирования между httpclient и okhttp (#I4FRR5)
  • fix: баг при отправке POST запроса, когда url пустой (#I4F3XS)
  • fix: исключения в retrywhen не выбрасываются, происходит только одно повторное выполнение после исключения (#I4E4X7)
  • fix: ошибка I/O при последовательной асинхронной отправке запросов через httpclient (#I47FD7)

Переработка кода:

  • refactor: переработка кода backend: часть Body формы
  • refactor: переработка backend: okhttp3
  • refactor: переработка backend: httpclient
  • refactor: переработка backend: логика асинхронных запросов

Оптимизация кода:

  • optimize: улучшение обработки ответов на некоторые ошибки в Forest (#I4EIDJ)

Другие изменения кода:

  • add: добавлен класс ForestBody
  • add: добавлен класс Validations
  • remove: удалён ненужный исполнитель запросов класс OkHttp3
Последнее сообщение коммита: update: new version -> 1.5.12
11.03.2025 04:21
GitLife Service Account

в версии v1.5.11 были исправлены несколько ошибок

ИСПРАВЛЕННЫЕ ОШИБКИ

  • fix: конфигурация connect-timeout не может быть распознана в Spring Boot 1.x (#I4ECR3)

УПРАВЛЕНИЕ ВНУТРЕННЕЙ ЭФФЕКТИВНОСТЬЮ

  • optimize: усиление информации об ошибках в шаблонах строк (#I4EC9V)
Последнее сообщение коммита: update: new version -> 1.5.11
11.03.2025 04:21
GitLife Service Account

версия v1.5.10 выпущена; этот выпуск解决了由于前一版本更改而出现的问题

  • fix: пустой указатель, вызванный переинтерпретацией URL

  • fix: пустой указатель, вызванный переинтерпретацией URL

Последнее сообщение коммита: update: new version -> 1.5.10
11.03.2025 04:21
GitLife Service Account

Версия v1.5.9 выпущена, в этом обновлении были исправлены проблемы с некорректной работой URL Encoder в некоторых случаях. Для этого был реализован новый подход к парсингу и кодировке URL, отказавшись от использования встроенных объектов URI и класса URLEncoder из Java. Также была внедрена строковая шаблонизация для семантического представления URL.

Автоматическое распознание параметров шаблона как части URL

/**
 * Новый вариант позволяет определять {a} и {b} как параметры запроса URL
 * Эти параметры будут закодированы согласно требованиям параметров запроса: символ '&' будет экранирован
 * В то время как {path} будет распознан как часть пути URL
 * Этот параметр будет закодирован согласно требованиям пути URL: символ '&' не будет экранирован
 */
@Get("/data/{path}? a={a}&b={b}")
String getData(@Var("path") String path, @Var("a") String a, @Var("b") String b);
```#### Различие между `{}` и `${}$`
##### `{}` представляет собой параметр запроса
Шаблон параметра `{}`, используемый в контексте `?a={a}`, рассматривается как параметр запроса URL. Даже если значение переменной может содержать несколько параметров, таких как `"1&x=10&y=20"`, это значение будет экранировано как один параметр запроса.
```java
@Get("http://localhost/data?  a={a}&b={b}")
String getData(@Var("a") String a, @Var("b") String b)
// Полученный URL будет выглядеть так:
// http://localhost/data?  a=1%26x%3D10%26y%3D20&b=hello
// То есть URL будет содержать только два параметра запроса: a и b
myClient.getData("1&x=10&y=20", "hello");
${}$ может содержать несколько параметров запроса

Шаблон параметра ${}$ можно рассматривать как замену строки, после которой параметры URL будут проанализированы. Поэтому каждый параметр шаблона может содержать несколько параметров, которые затем будут распознаны как отдельные параметры.

@Get("http://localhost/data?  a=${a}&b=${b}")
String getData(@Var("a") String a, @Var("b") String b)
// Полученный URL будет выглядеть так:
// http://localhost/data?  a=1&x=10&y=20&b=hello
// То есть URL будет содержать четыре параметра запроса: a, x, y и b
myClient.getData("1&x=10&y=20", "hello");

Рекомендация использовать {} как шаблон параметра

Учитывая особенности этих двух типов шаблонов параметров, они могут использоваться в различных ситуациях.Однако обычно рекомендуется использовать {} поскольку он более структурирован и семантичен, что делает его легче понять и менее склонным к ошибкам, особенно при передаче одного URL в качестве параметра другому URL.
Например, если требуется передать под-URL с параметрами: https://search.gitee.com/?type=repository&q=forest
После получения в родительском URL это будет выглядеть так: http://localhost/data?call={url}
Если же использовать ${url}$, возникнут проблемы.

@Get("/data?call=${url}")
String getData(@Var("url") String url);

// Последний сгенерированный URL выглядит так
// http://localhost/data?call=https://search.gitee.com/?type=repository&q=forest

На первый взгляд всё в порядке, но последняя часть `&q=forest` будет воспринята как параметр запроса родительского URL, хотя она должна относиться к под-URL.
Если использовать `{url}`, то проблема исчезает, даже если позже будут добавлены другие параметры.
```java
@Get("/data?call={url}&x={x}")
String getData(@Var("url") String url, @Var("x") String x);
// Последний сгенерированный URL выглядит так
// http://localhost/data?call=https://search.gitee.com/?type=repository%26q=forest&x=xxx

Как видно, разделитель параметров запроса & внутри под-URL был экранирован, что решило конфликт между параметрами под-URL и параметрами родительского URL (например, x).#### ИСПРАВЛЕННЫЕ ОШИБКИ

  • исправление: неправильно закодированное значение URI с помощью URLEncoder (#I4DUFG)
Последнее сообщение коммита: update: new version -> 1.5.9
11.03.2025 04:20
GitLife Service Account

Версия v1.5.8 выпущена, в ней исправлены следующие ошибки:

  • fix: При использовании @DownloadFile для скачивания файлов в некоторых средах происходил блокирующий запрос (#I4DLBI)
Последнее сообщение коммита: update: new version -> 1.5.8
11.03.2025 04:20
GitLife Service Account

Версия v1.5.7 выпущена, в основном решена проблема зависимости от пакета google protobuf.

Исправленные ошибки:

  • fix: зависимость ответа от пакета google protobuf (#I4DKQW)
Последнее сообщение коммита: update: new version -> 1.5.7
11.03.2025 04:20
GitLife Service Account

версия v1.5.6 выпущена, в этом обновлении были исправлены некоторые ошибки

Новые возможности:

  • feat: детализация timeout на connectTimeout и readTimeout (#I4DH21)

Исправленные ошибки:

  • fix: ошибка зависимости для пакета Google Protobuf (#I4DDZY)
  • fix: настройка forest.connect-timeout не работает (#I45298)
Последнее сообщение коммита: feat: #I4DH21 将timeout细化为connectTimeout和readTimeout
11.03.2025 04:20
GitLife Service Account

Версия v1.5.5 выпущена, в этой версии основное внимание уделено поддержке Protocol Buffers (Protobuf) и исправлению нескольких ошибок.

Поддержка Protobuf

@Post(
    url = "/proto",
    contentType = ContentType.APPLICATION_OCTET_STREAM)
ProtobufProto.Data sendProtobufData(@ProtobufBody ProtobufProto.Data data);

Быстрые аннотации для смены бэкэнда

// Переключение на okhttp3
@OkHttp3
@Post("/data1")
String sendData1(@Body MyUser user);

// Переключение на HttpClient
@HttpClient
@Post("/data2")
String sendData2(@Body MyUser user);

Новые возможности:

  • feat: возможность задания конвертации сериализатора для каждого запроса (#I4CLV8)
  • feat: поддержка двоичных типов данных в теле запроса (#I4D4GY)
  • feat: поддержка протокола Protobuf в теле запроса (#I4D4JT)
  • feat: зависимость пакета конвертора при необходимости (#I29XE0)

Исправленные ошибки:

  • fix: метод getAttribute работает некорректно при многопоточной работе (#I4D5KS)
  • fix: вызовы addQuery или addBody в методе onRetry приводят к неработоспособности API (#I4CZS5)

Изменения в коде:

  • add: аннотация @OkHttp3
  • add: аннотация @HttpClient
  • add: метод ForestRequest.type(ForestRequestType type)
  • add: метод ForestLogHandler.logContent(String content)

Отдельное спасибо:

@yakax

Последнее сообщение коммита: fix: #I4D5KS getAttribute方法在多线程情况下返回值会串
11.03.2025 04:20
GitLife Service Account

Forest v1.5.4 выпущена

Основной акцент в этом выпуске сделан на исправление оставленных проблем, а также добавлении новых интерфейсов.

Интерфейсы для работы с параметрами запроса URL

  1. Добавление Map как параметров запроса URL
// Каждый ключ-значение пары из Map будет добавлено как параметр запроса
Map<String, Object> map = new LinkedHashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);

Forest.get("/")
     // Добавляем Map в качестве параметра запроса
    .addQuery(map)
     // Выполняем запрос
    .execute();
// Параметры запроса будут выглядеть так: a=1&b=2&c=3
  1. Добавление массивов и списков в параметры запроса URL
// Добавление списка в параметры запроса
Forest.get("/")
     .addQuery("a", Arrays.asList(1, 2, 3))
     .execute();
// Параметры запроса будут выглядеть так: a=1&a=2&a=3

// Добавление массива в параметры запроса
Forest.get("/")
     .addQuery("a", new Object[]{1, 2, 3})
     .execute();
// Параметры запроса будут выглядеть так: a=1&a=2&a=3
  1. Добавление массивов и списков в параметры запроса URL (с использованием [])
// Добавление списка в параметры запроса с []
Forest.get("/")
     .addArrayQuery("a", Arrays.asList(1, 2, 3))
     .execute();
// Параметры запроса будут выглядеть так: a[]=1&a[]=2&a[]=3

// Добавление массива в параметры запроса с []
Forest.get("/")
     .addArrayQuery("a", new Object[]{1, 2, 3})
     .execute();
// Параметры запроса будут выглядеть так: a[]=1&a[]=2&a[]=3
  1. Добавление JSON данных в параметры запроса URL```java
    // Добавление списка в параметры запроса с []
    Forest.get("/")
    .addJSONQuery("a", Arrays.asList(1, 2, 3))
    .execute();
    // Параметры запроса будут выглядеть так: a=[1,2,3]
    // Обратите внимание, что JSON данные будут закодированы через URLEncoder
    // Таким образом, конечные параметры запроса будут выглядеть так: a=%5B1%2C2%2C3%5D

- fix: зависимость от библиотеки Guava (#I4CC9B)
- fix: проблемы сериализации списков при использовании аннотации `@Query` для параметров типа `Map` (#I4C8UC)
- fix: проблемы многопоточности

## Изменения в коде

- update: удалены лишние DEBUG логи
- add: метод `ForestLogHandler.logContent(String content)`
- add: метод `ForestRequest.addQuery(String name, Collection collection)`
- add: метод `ForestRequest.addQuery(String name, Object... array)`
- add: метод `ForestRequest.addArrayQuery(String name, Collection collection)`
- add: метод `ForestRequest.addArrayQuery(String name, Object... array)`
Последнее сообщение коммита: udpate: new version -> 1.5.4
11.03.2025 04:19
GitLife Service Account

v1.5.3 версия выпущена, в которой было добавлено множество новых функций, среди которых есть значительные обновления.

Основные изменения

1. Добавлена быстрая работа с Forest

Ранее при использовании Forest требовалось определять интерфейсный класс, что удовлетворяло большинство ситуаций. Однако это могло усложнять быстрый доступ к URL.

Поэтому в новой версии был добавлен удобный интерфейс, позволяющий немедленно использовать его без необходимости определения интерфейса:```java
// GET запрос
// Получение данных типа String
String str = Forest.get("/").executeAsString();
// POST запрос
// Получение данных типа MyResult
MyResult myResult = Forest.post("/")
.execute(MyResult.class);
// Передача параметров через TypeReference
// Для получения данных с сложными типами
Result<List> userList = Forest.post("/")
.execute(new TypeReference<List<Result<List>>>() {});
// Определение различных параметров
// Получение данных типа Map
Map<String, Object> map = Forest.post("/")
.backend("okhttp3") // Установка бэкэнда как okhttp3
.contentTypeJson() // Установка заголовка Content-Type как application/json
.host("127.0.0.1") // Установка хоста адреса как 127.0.0.1
.port(8080) // Установка порта адреса как 8080
.addBody("a", 1) // Добавление элемента body (пар ключ-значение): a, 1
.addBody("b", 2) // Добавление элемента body (пар ключ-значение): b, 2
.maxRetryCount(3) // Установка максимального количества попыток повторной отправки запроса как 3
.onSuccess((data, req, res) -> { log.info("успешно!"); }) // Установка функции обратного вызова onSuccess
.onError((ex, req, res) -> { log.info("ошибка!"); }) // Установка функции обратного вызова onError
.successWhen((req, res) -> res.noException() && res.statusOk()) // Установка функции обратного вызова successWhen
.executeAsMap(); // Выполнение запроса и получение объекта типа Map


##### 2.1 Аннотация `@Success`
Сначала требуется определить реализацию интерфейса SuccessWhen

```java
public class TestSuccessWhen implements SuccessWhen {
    /**
     * Условие успешного выполнения запроса
     * @param req Объект запроса Forest
     * @param res Объект ответа Forest
     * @return Успешность выполнения запроса
     */
    @Override
    public boolean successWhen(ForestRequest req, ForestResponse res) {
        // Отсутствие ошибок и состояние кода в нормальном диапазоне и состояние кода не равно 203
        // Конечно, здесь можно указать другие условия, например, получить бизнес-данные с помощью res.getData() или res.getContent()
        // Затем использовать бизнес-данные для проверки успешности запроса
        return res.noException() && res.statusOk() && res.getStatusCode() != 203;
    }
}

Добавьте аннотацию @Success к методу запроса в Forest

@Get("http://localhost:${port}/")
@Success(condition = TestSuccessWhen.class)
String getData();

Если после вызова метода getData() возвращается код состояния 203, это будет считаться неудачей запроса. Если количество попыток повторной отправки больше нуля, будет выполнена задача повторной отправки. Если нет доступных попыток повторной отправки, будет выполнен процесс обработки ошибок.

2.2 Использование аннотации @RetryСначала определим реализацию интерфейса RetryWhen.
public class TestRetryWhen implements RetryWhen {
    /**
     * Условие для повторной отправки запроса
     * @param request объект запроса Forest
     * @param response объект ответа Forest
     * @return следует ли повторить отправку
     */
    @Override
    public boolean retryWhen(ForestRequest request, ForestResponse response) {
        // Если код состояния ответа равен 203, то повторяем отправку, хотя сам запрос может быть успешным
        // Конечно, здесь можно указать другие условия, например, получить бизнес-данные с помощью res.getData() или res.getConent()
        // Затем использовать бизнес-данные для проверки необходимости повторной отправки
        return response.statusIs(203);
    }
}

Добавьте аннотацию @Retry к методу запроса в Forest

// maxRetryCount - максимальное количество повторных отправок
// maxRetryInterval - максимальный интервал времени между повторными отправками, в миллисекундах
// condition - условие для повторной отправки, то есть реализация интерфейса RetryWhen
@Get("http://localhost:${port}/")
@Retry(maxRetryCount = "3", maxRetryInterval = "10", condition = TestRetryWhen.class)
String sendData();

При вызове метода sendData() если возвращается код состояния 203, это будет считаться необходимостью повторной отправки. Если количество попыток повторной отправки больше нуля, будет выполнена задача повторной отправки.
Если нет доступных попыток повторной отправки, будет выполнен процесс обработки успешного запроса.##### 2. 3 Различия между двумя типами повторной отправки

Может возникнуть вопрос, почему используется аннотация RetryWhen, если можно было бы просто использовать условие успеха в аннотации SuccessWhen.Механизм повторной отправки в Forest работает следующим образом:

  1. Сначала проверяется успешность запроса, при неудаче запускается повторная отправка;
  2. При успешном запросе проверяется, соответствует ли он условиям для повторной отправки, и если да, запускается повторная отправка.
Разница между ними заключается в следующем:

Запросы, повторные попытки которых происходят после неудачной попытки, переходят в состояние ошибки при последней неудачной попытке (например, вызывается метод onError).

Запросы, повторные попытки которых происходят вследствие выполнения условий повторной попытки, считаются успешными, если последняя попытка также завершается успешно, тогда они переходят в состояние успеха (например, вызывается метод onSuccess).

Краткое описание: successWhen — повторяет попытки при неудаче; retryWhen — повторяет попытки даже при успехе.

2.4 Функция обратного вызова OnRetry

Независимо от того, какую стратегию повторной попытки используют запросы, перед отправкой повторной попытки всегда будет вызвана функция обратного вызова OnRetry.
Функцию обратного вызова onRetry можно реализовать в интерцепторе.

public class TestRetryInterceptor implements Interceptor<Object> {

    /**
     * Вызов функции обратного вызова onRetry перед повторной попыткой
     *
     * @param request объект запроса Forest
     * @param response объект ответа Forest
     */
    @Override
    public void onRetry(ForestRequest request, ForestResponse response) {

Также следует отметить, что в данном тексте используется английский язык, поэтому перевод осуществляется именно на русский язык. // Добавляем текущее количество повторных попыток в атрибуты объекта запроса Forest
request.addAttachment("retry-interceptor", request.getCurrentRetryCount());
}
}

Связываем интерцептор, который реализует метод `onRetry`, с соответствующим интерфейсом.
```java
@BaseRequest(baseURL = "http://localhost:${port}/", interceptor = TestRetryInterceptor.class)
public interface RetryClient {
   @Get("/")
   @Retry(maxRetryCount = "${0}", maxRetryInterval = "${1}", condition = TestRetryWhen.class)
   ForestRequest<String> testRetryRequest(int retryCount, long retryInterval);
}```java
   @Get("/")
   @Retry(maxRetryCount = "${0}", maxRetryInterval = "${1}", condition = TestRetryWhen.class)
   String testRetry(int retryCount, long retryInterval, OnSuccess<String> onSuccess);
}

Другие новые возможности

Новые возможности:

feat: Быстрые интерфейсы Forest (#I4893Q)
feat: Поддержка глобальных переменных динамического привязывания методов (#I478N2)
feat: Поддержка шаблонов строк с использованием properties (#I3P1QK)
feat: Поддержка получения причинного сообщения ответа, то есть текстового состояния ответа (#I4BJVF)
feat: Создание пользовательских объединённых аннотаций (#I4BISF)
feat: Условия успешности запроса могут быть настроены пользователем (#I4AEMT)
feat: Возможность динамической установки адреса хоста и номера порта (#I4AEJ8)
feat: Настройка условий повторной попытки (#I493N3)
feat: Введение функции обратного вызова OnRetry (#I493N6)
feat: Добавлено аннотация @Headers
feat: Правила наследования для запросов Forest
feat: Автоматическое управление переадресацией
feat: Поддержка глобальных переменных с динамическим связыванием методов
feat: Отображение имени бэкенд-фреймворка в логах запросов
feat: Создание подпроекта forest-mock

fix: При пустом `Map` в POST-запросе невозможно преобразовать его в JSON-строку `{}`  
fix: Параметры фильтра всегда являются первым параметром  
fix: Пользовательские заголовки `Content-Type` заменяются на верхний регистр  
fix: В проектах Spring отсутствие конфигурации конвертора приводит к невозможности найти `Converter`  
fix: Ответ без заголовков `Content-Type` и `Content-Encoding` не может быть правильно распознан  
fix: При получении ответа 302 запрос 302-го заголовка недоступен  
fix: Недоступность инициализации `SpringSSLKeyStore` в Spring  
fix: Конверторы с параметрами `ForestConfiguration` не могут быть корректно инициализированы в Spring Boot  
fix: Ошибки стека при длительной работе многопоточных запросов на загрузку файлов  
fix: Несовместимость интерфейса `BeanPostProcessor` в ранних версиях Spring Boot#### Улучшения:
opt: Улучшение методов класса StringUtils  
opt: Улучшение методов класса URLUtils  

#### Изменения кода:
add: Класс SpringForestProperties  
add: Добавление свойства responseEncoding во все аннотации запросов (например, `@Request`, `@Get`)  
add: Класс SpringForestObjectFactory  
add: Метод isRedirection в классе ForestResponse  
add: Метод getRedirectionLocation в классе ForestResponse  
add: Метод redirectionRequest в классе ForestResponse  
add: Метод clone в классе ForestHeaderMap  
add: Метод clone в классе ForestQueryMap  
refactor: Свойство retryCount больше не рекомендуется использовать  
update: Удаление MethodLifeCycle  
refactor: Изменение логики сканирования типов в Forest  
refactor: Преобразование класса TypeReference в абстрактный  

#### Благодарности:
Благодарим участников за их вклад, порядок благодарностей не имеет значения  
@CHMing  
@ifaxin
Последнее сообщение коммита: update: new version -> 1.5.3
11.03.2025 04:17
GitLife Service Account

Новые возможности:

  • feat: #I3E9T4
  • feat: #I3SR0L
  • feat: #I3P1R0
  • feat: #I3SUSL
  • feat: #I3E63M

Устранённые проблемы:

  • fix: #I3IUKC
  • fix: #I3RBR2
  • fix: Удаление protobuf декодера в соответствии с типом возвращаемого значения
  • fix: #I3E1MF
  • fix: #I3AJSD
  • fix: #I3IUKD
  • fix: При отсутствии протокола в одностороннем SSL возникает пустой указатель
  • fix: Пустой указатель при statusCode
  • fix: Статус 404 при отсутствии сетевой ошибки
  • fix: Исправление опечатки в имени метода getDateType -> getDataType

Другие изменения:

  • update: Обновление версии gson до 2.8.6
  • refactor: Установка единой версии spring-boot
  • update: Удаление QLExpress
  • add: Аннотация @URLEncode
  • add: Класс URLEncodeLifeCycle

Отдельное спасибо:

Отдельное спасибо этим участникам (порядок нумерации не имеет значения).

Последнее сообщение коммита: update: new version 1.5.1
11.03.2025 04:17
GitLife Service Account

Этот выпуск является официальным и включает следующие новые возможности и изменения:

Новые возможности:

  • feat: #I3B3UZ
  • feat: #I3DOAP
  • feat: #I3E0FD

Исправленные проблемы:

  • fix: #I3DAEQ

Изменения кода:

  • add: метод ForestConfiguration#isVariableDefined
  • add: аннотация @Var
  • add: класс ResourceRequestBody
  • add: класс ResourceRequestBodyBuilder
  • add: класс MultipartRequestBody
  • add: класс MultipartRequestBodyBuilder
  • add: класс SupportFormUrlEncoded
  • refactor: переименование DataVariableLifeCycle в VariableLifeCycle
  • refactor: использование паттерна конструктора для парсинга объекта Body
  • refactor: переименование файла ForestVariableUndefined.java в ForestVariableUndefinedException

Изменения зависимостей Maven:

  • update: обновление версий Spring-Core и Spring-Webmvc
  • update: обновление версии JUnit
Последнее сообщение коммита: update: new version v1.5.0
Предпросмотр версии
11.03.2025 04:17
GitLife Service Account

Исправленные проблемы:

-修复:#I3B5VH
-修复:#I3B49O

Исправленные проблемы:

  • FIX: #I3B5VH
  • FIX: #I3B49O
Последнее сообщение коммита: update: 1.5.0-RC7
Предпросмотр версии
11.03.2025 04:17
GitLife Service Account

1.5.0-RC6 выпущена, в этом выпуске содержится несколько изменений, которые не совместимы с предыдущими версиями:

(1) Maven зависимость spring-boot-starter-forest была заменена на forest-spring-boot-starter.
(2) Пакет, содержащий аннотацию @ForestScan, был переименован в com.dtflys.forest.springboot. В коде требуется выполнить импорт пакета заново.

Зависимость в Maven теперь выглядит следующим образом:

<dependency>
    <groupId>com.dtflys.forest</groupId>
    <artifactId>forest-spring-boot-starter</artifactId>
    <version>1.5.0-RC6</version>
</dependency>

Новые возможности:

  • feat: #I3AHLC
  • feat: Параметры запроса могут выбирать, закодированы ли они в URL

Исправленные проблемы:

  • fix: #I3AJSD
  • fix: При многомодульной разработке несколько аннотаций @ForestScan могут сканироваться только для одного из базовых пакетов
  • fix: Пропущено условие проверки типа boolean

Изменения, несовместимые с предыдущими версиями:

  • refactor: Групповой ID 'spring-boot-starter-forest' был изменён на 'forest-spring-boot-starter'.
  • refactor: Модуль 'spring-boot-starter-forest' был переименован в 'forest-spring-boot-starter'.
  • refactor: Был переименован пакет внутри модуля 'forest-spring-boot-starter', он теперь называется 'com.dtflys.forest.springboot'.

Благодарность участникам, внесшим свой вклад в этот выпуск:

Последнее сообщение коммита: update: new version 1.5.0-RC6
1
https://api.gitlife.ru/oschina-mirror/dromara-forest.git
git@api.gitlife.ru:oschina-mirror/dromara-forest.git
oschina-mirror
dromara-forest
dromara-forest