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

OSCHINA-MIRROR/lianjiatech-retrofit-spring-boot-starter

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

com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory

  • retrofit2.converter.jackson.JacksonConverterFactory

Глобальные настройки адаптера вызова

global-call-adapter-factories:

Настройки глобального журнала

global-log:

  • Включение журнала: true
  • Уровень глобального журнала: info
  • Стратегия глобального журнала: basic
  • Агрегация журналов запросов: true

Глобальная конфигурация повторов

global-retry:

  • Включение глобальных повторов: false
  • Интервал времени между повторами (мс): 100
  • Максимальное количество повторов: 2
  • Правила повтора:
    • response_status_not_2xx
    • occur_io_exception

Конфигурация глобального тайм-аута

global-timeout:

  • Время ожидания чтения (мс): 10 000
  • Время ожидания записи (мс): 10 000
  • Время ожидания соединения (мс): 10 000
  • Полное время ожидания вызова (мс): 0

Настройка деградации и понижения уровня обслуживания

degrade:

  • Тип деградации: none (по умолчанию)
  • Глобальная настройка понижения уровня сервиса с помощью Sentinel:
    • Включение: false
    • Пороги для каждой стратегии деградации (среднее время отклика в мс, доля аномалий от 0 до 1, количество аномалий от 1 до N): count = 1 000, time-window = 5, grade = 0
  • Глобальная настройка понижения уровня сервиса с использованием resilience4j:
    • Включение: false
    • Имя конфигурации CircuitBreakerConfig из @link CircuitBreakerConfigRegistry для использования в качестве глобальной конфигурации понижения уровня: defaultCircuitBreakerConfig

Автоматическая установка области действия PathMathInterceptor на prototype

auto-set-prototype-scope-for-path-math-interceptor: true

Расширенные функции

Конфигурация тайм-аутов

Если вам нужно изменить только время ожидания OkHttpClient, вы можете сделать это с помощью соответствующих полей @RetrofitClient или глобальной конфигурации.

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

Чтобы настроить другие параметры OkHttpClient, можно создать собственный OkHttpClient. Вот как это делается:

  1. Реализуйте интерфейс SourceOkHttpClientRegistrar и зарегистрируйте OkHttpClient с помощью метода SourceOkHttpClientRegistry#register().
@Component
public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar {

   @Override
   public void register(SourceOkHttpClientRegistry registry) {
      // Регистрация customOkHttpClient с временем ожидания 1 секунда
      registry.register("customOkHttpClient", new OkHttpClient.Builder()
              .connectTimeout(Duration.ofSeconds(1))
              .writeTimeout(Duration.ofSeconds(1))
              .readTimeout(Duration.ofSeconds(1))
              .addInterceptor(chain -> chain.proceed(chain.request()))
              .build());
   }
}
  1. Укажите используемый OkHttpClient через @RetrofitClient.sourceOkHttpClient для каждого интерфейса.
@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "customOkHttpClient")
public interface CustomOkHttpUserService {

   /**
    * Получение информации о пользователе по id
    */
   @GET("getUser")
   User getUser(@Query("id") Long id);
}

Обратите внимание: компоненты не используют указанный OkHttpClient напрямую, а создают на его основе новый.

Аннотированные перехватчики

Компоненты предоставляют аннотированные перехватчики, которые поддерживают сопоставление путей URL. Для их использования выполните следующие шаги:

  1. Наследуйте BasePathMatchInterceptor.
  2. Используйте аннотацию @Intercept для указания используемого перехватчика.

Если вам нужно использовать несколько перехватчиков, просто добавьте несколько аннотаций @Intercept к интерфейсу.

Реализация BasePathMatchInterceptor

@Component
public class PathMatchInterceptor extends BasePathMatchInterceptor {
   @Override
   protected Response doIntercept(Chain chain) throws IOException {
      Response response = chain.proceed(chain.request());
      // Добавляем заголовок path.match в ответ
      return response.newBuilder().header("path.match", "true").build();
   }
}

По умолчанию компонент автоматически устанавливает область действия BasePathMatchInterceptor как prototype. Вы можете отключить эту функцию, установив retrofit.auto-set-prototype-scope-for-path-math-interceptor=false. После отключения вам необходимо вручную установить область действия на prototype.

@Component
@Scope("prototype")
public class PathMatchInterceptor extends BasePathMatchInterceptor {
    
}

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

@RetrofitClient(baseUrl = "${test.baseUrl}")
@Intercept(handler = PathMatchInterceptor.class, include = {"/api/user/**"}, exclude = "/api/user/getUser")
// @Intercept() Если вам нужно использовать несколько путей сопоставления перехватчиков, продолжайте добавлять @Intercept.
public interface InterceptorUserService {

   /**
    * Получение имени пользователя по id
    */
   @POST("getName")
   Response<String> getName(@Query("id") Long id);

   /**
    * Получение информации о пользователе по id
    */
   @GET("getUser")
   Response<User> getUser(@Query("id") Long id);

} **Вот перевод текста на русский язык:**

«Конфигурация `@Intercept` выше означает: перехватывать запросы, которые соответствуют пути `/api/user/**`, за исключением `/api/user/getUser`, и обрабатывать их с помощью `PathMatchInterceptor.

### Создание пользовательских перехватчиков

Иногда нам нужно динамически передавать некоторые параметры в «перехватчик» и использовать эти параметры при перехвате. В этом случае мы можем создать «пользовательский перехватчик», выполнив следующие шаги:

1. Создать аннотацию. Она должна быть помечена как `@InterceptMark`, а также содержать поля `include`, `exclude` и `handler`.
2. Наследовать от `BasePathMatchInterceptor`, чтобы написать обработчик для перехватчика.
3. Использовать пользовательскую аннотацию в интерфейсе.

Например, если нам нужно добавить информацию о подписи в заголовке запроса (accessKeyId и accessKeySecret), чтобы отправить HTTP-запрос, мы можем использовать пользовательскую аннотацию `@Sign` для реализации этой функции.

#### Пользовательская аннотация `@Sign`

```java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
    
    String accessKeyId();

    String accessKeySecret();

    String[] include() default {"/**"};

    String[] exclude() default {};

    Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}

В аннотации @Sign указано, что обработчиком является SignInterceptor.

Реализация SignInterceptor

@Component
@Setter
public class SignInterceptor extends BasePathMatchInterceptor {

   private String accessKeyId;

   private String accessKeySecret;

   @Override
   public Response doIntercept(Chain chain) throws IOException {
      Request request = chain.request();
      Request newReq = request.newBuilder()
              .addHeader("accessKeyId", accessKeyId)
              .addHeader("accessKeySecret", accessKeySecret)
              .build();
      Response response = chain.proceed(newReq);
      return response.newBuilder().addHeader("accessKeyId", accessKeyId)
              .addHeader("accessKeySecret", accessKeySecret).build();
   }
}

Обратите внимание: поля accessKeyId и accessKeySecret должны иметь метод setter.

Значения полей accessKeyId и accessKeySecret перехватчика будут автоматически введены на основе значений accessKeyId() и accessKeySecret() в аннотации @Sign. Если в аннотации указаны заполнители, то будут использоваться значения из конфигурации.

Использование @Sign в интерфейсах

@RetrofitClient(baseUrl = "${test.baseUrl}")
@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", include = "/api/user/getAll")
public interface InterceptorUserService {

   /**
    * Запрос всех пользовательских данных
    */
   @GET("getAll")
   Response<List<User>> getAll();

}

Ведение журнала

Компонент поддерживает глобальное ведение журнала и декларативное ведение журнала.

Глобальное ведение журнала

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

retrofit:
   # Конфигурация глобального ведения журнала
   global-log:
      # Включить ведение журнала
      enable: true
      # Уровень глобального ведения журнала
      log-level: info
      # Стратегия глобального ведения журнала
      log-strategy: basic
      # Агрегировать ли журналы запросов
      aggregate: true
      # Имя журнала, по умолчанию — полное имя класса {@link LoggingInterceptor}
      logName: com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor

Существует четыре стратегии ведения журнала:

  • NONE: не вести журнал.
  • BASIC: регистрировать строки запросов и ответов.
  • HEADERS: регистрировать строки запросов, ответов и соответствующие заголовки.
  • BODY: регистрировать строки запросов, ответов, соответствующие заголовки и тела (если есть).

Декларативное ведение журнала

Если необходимо регистрировать только часть запросов, можно использовать аннотацию @Logging в соответствующем интерфейсе или методе.

Расширение ведения журнала

Для изменения поведения ведения журнала можно наследовать класс LoggingInterceptor и настроить его как Spring bean.

Повторные попытки

Компонент поддерживает глобальные повторные попытки и декларативные повторные попытки.

Глобальные повторные попытки

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

retrofit:
  # Конфигурация глобальных повторных попыток
  global-retry:
     # Включить ли глобальные повторные попытки
     enable: false
     # Интервал времени между повторными попытками в миллисекундах
     interval-ms: 100
     # Максимальное количество повторных попыток
     max-retries: 2
     # Правила повторных попыток
     retry-rules:
        - response_status_not_2xx
        - occur_io_exception

Правила повторных попыток могут быть настроены тремя способами:

  • RESPONSE_STATUS_NOT_2XX: повторить попытку, если статус ответа не равен 2xx.
  • OCCUR_IO_EXCEPTION: повторить попытку при возникновении исключения ввода-вывода.
  • OCCUR_EXCEPTION: повторить попытку при любом исключении.

Декларативные повторные попытки

Если только часть запросов требует повторной попытки, можно использовать аннотацию @Retry в соответствующем интерфейсе или методе.

Расширение повторных попыток

Чтобы изменить поведение повторных попыток, можно наследовать RetryInterceptor и настроить его как Spring bean.

Отключение и понижение уровня обслуживания

Отключение и понижение уровня обслуживания по умолчанию отключено, и в настоящее время поддерживаются две реализации: sentinel и resilience4j.

retrofit:
   # Конфигурация отключения и понижения уровня обслуживания
   degrade:
      # Тип отключения и понижения уровня обслуживания. По умолчанию none, что означает, что отключение и понижение уровня обслуживания не включены
      degrade-type: sentinel

Sentinel

Включите degrade-type=sentinel, затем объявите аннотацию @SentinelDegrade в соответствующем интерфейсе или методе, чтобы активировать Sentinel.

Не забудьте вручную импортировать зависимость Sentinel:


<dependency>
   <groupId>com.alibaba.csp</groupId>
   <artifactId>sentinel-core</artifactId>
   <version>1.6.3</version>
</dependency>

Кроме того, поддерживается глобальная конфигурация Sentinel для отключения и понижения уровня обслуживания:

retrofit:
  # Конфигурация отключения и понижения уровня обслуживания
  degrade:
    # Тип отключения и понижения уровня обслуживания. По умолчанию none, что означает, что отключение и понижение уровня обслуживания не включены
    degrade-type: sentinel
    # Глобальная конфигурация Sentinel для отключения и понижения уровня обслуживания
    global-sentinel-degrade:
      # Включить ли
      enable: true
      # ...другие глобальные конфигурации Sentinel

Resilience4j

Примечание: в тексте запроса присутствуют фрагменты кода на языке Java, но они не были переведены, так как не являются частью основного текста. Конфигурация: degrade-type=resilience4j. Затем в соответствующем интерфейсе или методе объявите @Resilience4jDegrade.

Не забудьте вручную импортировать Resilience4j:

<dependency>
   <groupId>io.github.resilience4j</groupId>
   <artifactId>resilience4j-circuitbreaker</artifactId>
   <version>1.7.1</version>
</dependency>

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

retrofit:
  # 熔断降级配置
  degrade:
    # 熔断降级类型。默认none,表示不启用熔断降级
    degrade-type: resilience4j
    # 全局resilience4j降级配置
    global-resilience4j-degrade:
      # 是否开启
      enable: true
      # 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置
      circuit-breaker-config-name: defaultCircuitBreakerConfig

Управление конфигурацией деградации:

Реализуйте интерфейс CircuitBreakerConfigRegistrar и зарегистрируйте CircuitBreakerConfig.

@Component
public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar {
   @Override
   public void register(CircuitBreakerConfigRegistry registry) {

         // 替换默认的CircuitBreakerConfig
         registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults());

         // 注册其它的CircuitBreakerConfig
         registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom()
                 .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED)
                 .failureRateThreshold(20)
                 .minimumNumberOfCalls(5)
                 .permittedNumberOfCallsInHalfOpenState(5)
                 .build());
   }
}

С помощью circuitBreakerConfigName укажите CircuitBreakerConfig. Включая retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name или @Resilience4jDegrade.circuitBreakerConfigName.

Расширение деградации и понижения:

Если пользователю необходимо использовать другую реализацию деградации и понижения, наследуйте BaseRetrofitDegrade и сделайте его конфигурацией Spring Bean.

Настройка fallback или fallbackFactory (необязательно):

Если @RetrofitClient не устанавливает fallback или fallbackFactory, при срабатывании деградации будет непосредственно выброшено исключение RetrofitBlockException. Пользователи могут настроить возвращаемое значение метода при деградации, установив fallback или fallbackFactory.

Обратите внимание: класс fallback должен быть реализацией текущего интерфейса, а класс fallbackFactory должен быть реализацией FallbackFactory, где T является универсальным параметром типа текущего интерфейса. Кроме того, экземпляры fallback и fallbackFactory должны быть настроены как Spring Bean.

Основное отличие fallbackFactory от fallback заключается в том, что он может воспринимать причину каждого сбоя деградации (cause).

Пример:

@Slf4j
@Service
public class HttpDegradeFallback implements HttpDegradeApi {

   @Override
   public Result<Integer> test() {
      Result<Integer> fallback = new Result<>();
      fallback.setCode(100)
              .setMsg("fallback")
              .setBody(1000000);
      return fallback;
   }
}
@Slf4j
@Service
public class HttpDegradeFallbackFactory implements FallbackFactory<HttpDegradeApi> {

   @Override
   public HttpDegradeApi create(Throwable cause) {
      log.error("触发熔断了! ", cause.getMessage(), cause);
      return new HttpDegradeApi() {
         @Override
         public Result<Integer> test() {
            Result<Integer> fallback = new Result<>();
            fallback.setCode(100)
                    .setMsg("fallback")
                    .setBody(1000000);
            return fallback;
         }
      };
   }
}

Декодер ошибок

Когда происходит ошибка запроса HTTP (включая возникновение исключения или данные ответа не соответствуют ожиданиям), декодер ошибок может декодировать информацию HTTP в пользовательское исключение. Вы можете указать текущий декодер ошибок интерфейса в аннотации @RetrofitClient errorDecoder(). Пользовательский декодер ошибок должен реализовать интерфейс ErrorDecoder.

Вызов HTTP между микросервисами

Наследование ServiceInstanceChooser

Пользователи могут самостоятельно реализовать интерфейс ServiceInstanceChooser для завершения логики выбора экземпляра службы и настроить его как Spring Bean. Для приложений Spring Cloud можно использовать следующую реализацию.

@Service
public class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser {
    
   private LoadBalancerClient loadBalancerClient;

   @Autowired
   public SpringCloudServiceInstanceChooser(LoadBalancerClient loadBalancerClient) {
      this.loadBalancerClient = loadBalancerClient;
   }

   /**
    * Chooses a ServiceInstance URI from the LoadBalancer for the specified service.
    *
    * @param serviceId The service ID to look up the LoadBalancer.
    * @return Return the uri of ServiceInstance
    */
   @Override
   public URI choose(String serviceId) {
      ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);
      Assert.notNull(serviceInstance, "can not found service instance! serviceId=" + serviceId);
      return serviceInstance.getUri();
``` #### 指定 `serviceId` и `path`

```java
@RetrofitClient(serviceId = "user", path = "/api/user")
public interface ChooserOkHttpUserService {

   /**
    * 根据 id 查询用户信息
    */
   @GET("getUser")
   User getUser(@Query("id") Long id);
}

Глобальный перехватчик

Глобальный прикладной перехватчик

Если нам нужно выполнить унифицированную обработку перехвата для всех запросов системы HTTP, мы можем реализовать глобальный перехватчик GlobalInterceptor и настроить его как spring Bean.

@Component
public class MyGlobalInterceptor implements GlobalInterceptor {
   @Override
   public Response intercept(Chain chain) throws IOException {
      Response response = chain.proceed(chain.request());
      // response 的 Header 加上 global
      return response.newBuilder().header("global", "true").build();
   }
}

Глобальный сетевой перехватчик

Реализуйте интерфейс NetworkInterceptor и настройте его как spring Bean.

Вызов адаптера

Retrofit может адаптировать объект типа Call<T> к типу возвращаемого значения метода с помощью CallAdapterFactory. Компонент расширяет некоторые реализации CallAdapterFactory:

  1. BodyCallAdapterFactory — синхронное выполнение HTTP-запроса, адаптация содержимого ответа тела к типу возвращаемого значения метода. Любой тип возвращаемого значения метода может использовать BodyCallAdapterFactory, который имеет самый низкий приоритет.
  2. ResponseCallAdapterFactory — синхронное выполнение HTTP-запроса, адаптация содержимого ответа тела к Retrofit.Response<T>, типу возвращаемого значения. Только методы с типом возвращаемого значения Retrofit.Response<T> могут использовать ResponseCallAdapterFactory.
  3. Адаптеры вызова, связанные с реактивным программированием.

Retrofit выбирает соответствующий CallAdapterFactory для выполнения адаптации в зависимости от типа возвращаемого значения метода. В настоящее время поддерживаются следующие типы возвращаемых значений:

String — адаптация содержимого тела ответа к строке. — Базовые типы (Long/Integer/Boolean/Float/Double) — адаптация содержимого тела ответа к базовому типу. — Любой тип Java — адаптация содержимого тела ответа к соответствующему объекту Java. — CompletableFuture<T> — адаптация содержимого тела ответа к объекту CompletableFuture<T>. — Void — не заботится о типе возвращаемого значения, можно использовать Void. — Response<T> — адаптация тела ответа к Response<T>. — Call<T> — без выполнения адаптации, напрямую возвращает объект Call<T>. — Mono<T> — тип возврата Project Reactor. — Single<T> — реактивный тип возврата Rxjava (поддерживает Rxjava2/Rxjava3). — Completable — реактивный тип возврата Rxjava, HTTP-запрос не имеет тела ответа (поддерживает Rxjava2/Rxjava3).

Можно расширить CallAdapter.Factory, унаследовав класс CallAdapter.Factory.

Компонент поддерживает настройку глобального адаптера вызова через retrofit.global-call-adapter-factories:

retrofit:
  # 全局转换器工厂(组件扩展的 CallAdaptorFactory 工厂已经内置,这里请勿重复配置)
  global-call-adapter-factories:
    # ...

Для каждого интерфейса Java также можно указать CallAdapter.Factory, используемый текущим интерфейсом, через @RetrofitClient.callAdapterFactories.

Рекомендуется: настроить CallAdapter.Factory как Spring Bean.

Кодировщик данных

Retrofit использует Converter для преобразования объектов, аннотированных @Body, в тело запроса и преобразования тела ответа в объект Java. Можно выбрать один из следующих Converter:

— Gson (https://github.com/google/gson): com.squareup.Retrofit:converter-gson. — Jackson (https://github.com/FasterXML/jackson): com.squareup.Retrofit:converter-jackson. — Moshi (https://github.com/square/moshi/): com.squareup.Retrofit:converter-moshi. — Protobuf (https://developers.google.com/protocol-buffers/): com.squareup.Retrofit:converter-protobuf. — Wire (https://github.com/square/wire): com.squareup.Retrofit:converter-wire. — Simple XML (http://simple.sourceforge.net/): com.squareup.Retrofit:converter-simplexml. — JAXB (https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html): com.squareup.retrofit2:converter-jaxb. — fastJson: com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory.

Компонент поддерживает конфигурацию глобального Converter.Factory через retrofit.global-converter-factories, по умолчанию используется retrofit2.converter.jackson.JacksonConverterFactory.

Если необходимо изменить конфигурацию Jackson, вы можете самостоятельно переопределить конфигурацию bean JacksonConverterFactory.

retrofit:
   # 全局转换器工厂
   global-converter-factories:
      - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
      - retrofit2.converter.jackson.JacksonConverterFactory

Также можно указать текущий интерфейс, используя @RetrofitClient.converterFactories.

Рекомендуется: настроить Converter.Factory как Spring Bean.

Мета-аннотации

Аннотации @RetrofitClient, @Retry, @Logging, @Resilience4jDegrade и другие поддерживают мета-аннотации, наследование и @AliasFor.


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Logging(logLevel = LogLevel.WARN)
@Retry(intervalMs = 200)
public @interface MyRetrofitClient {

   @AliasFor(annotation = RetrofitClient.class, attribute = "converterFactories")
   Class<? extends Converter.Factory>[] converterFactories() default {GsonConverterFactory.class};

   @AliasFor(annotation = Logging.class, attribute = "logStrategy")
   LogStrategy logStrategy() default LogStrategy.BODY;
}

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

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

1
https://api.gitlife.ru/oschina-mirror/lianjiatech-retrofit-spring-boot-starter.git
git@api.gitlife.ru:oschina-mirror/lianjiatech-retrofit-spring-boot-starter.git
oschina-mirror
lianjiatech-retrofit-spring-boot-starter
lianjiatech-retrofit-spring-boot-starter
master