Въведение в Spring Cloud OpenFeign

1. Общ преглед

В този урок ще опишем Spring Cloud OpenFeign - декларативен REST клиент за приложения на Spring Boot.

Feign улеснява писането на клиенти на уеб услуги с поддръжка на анотации с възможност за включване, която включва анотации на Feign и анотации JAX-RS.

Също така Spring Cloud добавя поддръжка за анотации на Spring MVC и за използване на същите HttpMessageConverters, както се използват в Spring Web.

Страхотно нещо при използването на Feign е, че не е нужно да пишем никакъв код за извикване на услугата, освен дефиниция на интерфейс.

2. Зависимости

Първо ще започнем, като създадем уеб проект Spring Boot и добавим зависимостта spring-cloud-starter-openfeign към нашия файл pom.xml :

 org.springframework.cloud spring-cloud-starter-openfeign 

Също така ще трябва да добавим зависимостите spring-cloud :

    org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import   

Можем да намерим най-новите версии на spring-cloud-starter-openfeign и spring-cloud-зависимостите на Maven Central.

3. Привиден клиент

След това трябва да добавим @EnableFeignClients към нашия основен клас:

@SpringBootApplication @EnableFeignClients public class ExampleApplication { public static void main(String[] args) { SpringApplication.run(ExampleApplication.class, args); } }

С тази анотация ние даваме възможност за сканиране на компоненти за интерфейси, които декларират, че са клиенти на Feign.

След това декларираме клиент на Feign, използвайки анотацията @FeignClient :

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/") public interface JSONPlaceHolderClient { @RequestMapping(method = RequestMethod.GET, value = "/posts") List getPosts(); @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json") Post getPostById(@PathVariable("postId") Long postId); }

В този пример конфигурирахме клиент за четене от JSONPlaceHolder API.

Аргументът стойност , предаден в анотацията @FeignClient, е задължително произволно име на клиента, докато с аргумента url указваме основния URL адрес на API.

Освен това, тъй като този интерфейс е клиент на Feign, можем да използваме Spring Web анотациите, за да декларираме API, до които искаме да се свържем.

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

Сега е много важно да се разбере, че всеки клиент на Feign е съставен от набор от персонализируеми компоненти.

Spring Cloud създава нов набор по подразбиране при поискване за всеки посочен клиент, използвайки класа FeignClientsConfiguration, който можем да персонализираме, както е обяснено в следващия раздел.

Горният клас съдържа тези зърна:

  • Декодер - ResponseEntityDecoder , който обгръща SpringDecoder, използван за декодиране на Response
  • Кодер - SpringEncoder , използван за кодиране на RequestBody
  • Регистратор - Slf4jLogger е регистраторът по подразбиране, използван от Feign
  • Договор - SpringMvcContract , който осигурява обработка на анотации
  • Feign-Builder - HystrixFeign.Builder, използван за конструиране на компонентите
  • Клиент - LoadBalancerFeignClient или клиент на Feign по подразбиране

4.1. Персонализирана конфигурация на боб

Ако искаме да персонализираме един или повече от тези зърна, можем да ги заменим с помощта на клас @Configuration , който след това добавяме към анотацията FeignClient :

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/", configuration = MyClientConfiguration.class)
@Configuration public class MyClientConfiguration { @Bean public OkHttpClient client() { return new OkHttpClient(); } }

В този пример казваме на Feign да използва OkHttpClient вместо стандартния за поддържане на HTTP / 2.

Feign поддържа множество клиенти за различни случаи на употреба, включително ApacheHttpClient , който изпраща повече заглавки с искането - например Content-Length, което някои сървъри очакват.

За да използваме тези клиенти, нека не забравяме да добавим необходимите зависимости към нашия файл pom.xml , например:

 io.github.openfeign feign-okhttp   io.github.openfeign feign-httpclient 

Можем да намерим най-новите версии на feign-okhttp и feign-httpclient в Maven Central.

4.2. Конфигуриране с помощта на свойства

Вместо да използваме клас @Configuration , можем да използваме свойствата на приложението, за да конфигурираме клиенти на Feign , както е показано в този пример application.yaml :

feign: client: config: default: connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic

С тази конфигурация задаваме времето за изчакване на 5 секунди и нивото на регистратора на основно за всеки деклариран клиент в приложението.

И накрая, можем да създадем конфигурацията по подразбиране като име на клиента, за да конфигурираме всички обекти @FeignClient , или можем да декларираме името на клиент на фиктив за конфигурация:

feign: client: config: jplaceholder:

Ако имаме и двете свойства на конфигурацията @Configuration и конфигурацията, свойствата на конфигурацията ще заменят стойностите на @Configuration .

5. Прехващачи

Добавянето на прехващачи е друга полезна функция, предоставена от Feign.

Прихващачите могат да изпълняват различни неявни задачи, от удостоверяване до регистриране, за всяка HTTP заявка / отговор.

В този раздел ще внедрим собствения си прехващач, както и ще използваме този, предоставен от Spring Cloud OpenFeign извън комплекта. И двете ще добавят основна заглавка за удостоверяване към всяка заявка .

5.1. Внедряване на RequestInterceptor

И така, в фрагмента по-долу, нека приложим нашия прехващач по поръчка:

@Bean public RequestInterceptor requestInterceptor() { return requestTemplate -> { requestTemplate.header("user", username); requestTemplate.header("password", password); requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType()); }; }

Also, to add the interceptor to the request chain, we just need to add this bean to our @Configuration class, or as we saw previously, declare it in the properties file:

feign: client: config: default: requestInterceptors: com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor

5.2. Using BasicAuthRequestInterceptor

Alternatively, we can use the BasicAuthRequestInterceptor class that the Spring Cloud OpenFeign provides:

@Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("username", "password"); }

It's simple as that! Now all the requests will contain the basic authentication header.

6. Hystrix Support

Feign supports Hystrix, so if we have enabled it, we can implement the fallback pattern.

With the fallback pattern, when a remote service call fails, rather than generating an exception, the service consumer will execute an alternative code path to try to carry out the action through another means.

To achieve the goal, we need to enable Hystrix adding feign.hystrix.enabled=true in the properties file.

This allows us to implement fallback methods that are called when the service fails:

@Component public class JSONPlaceHolderFallback implements JSONPlaceHolderClient { @Override public List getPosts() { return Collections.emptyList(); } @Override public Post getPostById(Long postId) { return null; } }

To let Feign know that fallback methods have been provided, we also need to set our fallback class in the @FeignClient annotation:

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/", fallback = JSONPlaceHolderFallback.class) public interface JSONPlaceHolderClient { // APIs }

7. Logging

For each Feign client, a logger is created by default.

To enable logging, we should declare it in the application.properties file using the package name of the client interfaces:

logging.level.com.baeldung.cloud.openfeign.client: DEBUG

Or, if we want to enable logging only for one particular client in a package, we can use the full class name:

logging.level.com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG

Note that Feign logging responds only to the DEBUG level.

The Logger.Level that we may configure per client indicates how much to log:

@Configuration public class ClientConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.BASIC; } }

There are four logging levels to choose from:

  • NONE – no logging, which is the default
  • BASIC – log only the request method, URL, and response status
  • HEADERS – log the basic information together with request and response headers
  • FULL – log the body, headers, and metadata for both request and response

8. Error Handling

Feign's default error handler, ErrorDecoder.default, always throws a FeignException.

Now, this behavior isn't always the most useful. So, to customize the Exception thrown, we can use a CustomErrorDecoder:

public class CustomErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { switch (response.status()){ case 400: return new BadRequestException(); case 404: return new NotFoundException(); default: return new Exception("Generic error"); } } }

След това, както направихме по-рано, трябва да заменим ErrorDecoder по подразбиране, като добавим боб към класа @Configuration :

@Configuration public class ClientConfiguration { @Bean public ErrorDecoder errorDecoder() { return new CustomErrorDecoder(); } }

9. Заключение

В тази статия обсъдихме Spring Cloud OpenFeign и прилагането му в просто примерно приложение.

Освен това видяхме как да конфигурираме клиент, как да добавяме прехващачи към нашите заявки и как да обработваме грешки, използвайки Hystrix и ErrorDecoder.

Както обикновено, всички примерни кодове, показани в този урок, са достъпни в GitHub.