Einführung in Spring Cloud OpenFeign

1. Übersicht

In diesem Tutorial beschreiben wir Spring Cloud OpenFeign - einen deklarativen REST-Client für Spring Boot-Apps.

Feign erleichtert das Schreiben von Webdienst-Clients durch die Unterstützung von steckbaren Anmerkungen, einschließlich Feign-Anmerkungen und JAX-RS-Anmerkungen.

Außerdem bietet Spring Cloud Unterstützung für Spring MVC-Anmerkungen und für die Verwendung derselben HttpMessageConverter wie in Spring Web.

Eine großartige Sache bei der Verwendung von Feign ist, dass wir keinen Code zum Aufrufen des Dienstes schreiben müssen, außer einer Schnittstellendefinition.

2. Abhängigkeiten

Zunächst erstellen wir ein Spring Boot-Webprojekt und fügen unserer pom.xml- Datei die Spring-Cloud-Starter-Openfeign- Abhängigkeit hinzu :

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

Außerdem müssen wir die Spring-Cloud-Abhängigkeiten hinzufügen :

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

Wir können die neuesten Versionen von Spring-Cloud-Starter-Openfeign und Spring-Cloud-Abhängigkeiten von Maven Central finden.

3. Kunden vortäuschen

Als nächstes müssen wir unserer Hauptklasse @EnableFeignClients hinzufügen :

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

Mit dieser Anmerkung aktivieren wir das Scannen von Komponenten nach Schnittstellen, die deklarieren, dass sie Feign-Clients sind.

Anschließend deklarieren wir einen Feign-Client mithilfe der Annotation @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); }

In diesem Beispiel haben wir einen Client zum Lesen aus den JSONPlaceHolder-APIs konfiguriert.

Der Wert Argument in der übergebenen @FeignClient Anmerkung ist ein obligatorischer, beliebiger Client - Name, während er mit dem URL - Argumente, wir die API Basis - URL angeben.

Da es sich bei dieser Schnittstelle um einen Feign-Client handelt, können wir die Spring Web-Annotationen verwenden, um die APIs zu deklarieren, die wir erreichen möchten.

4. Konfiguration

Jetzt ist es sehr wichtig zu verstehen, dass jeder Feign-Client aus einer Reihe anpassbarer Komponenten besteht.

Spring Cloud erstellt bei Bedarf für jeden benannten Client einen neuen Standardsatz mithilfe der FeignClientsConfiguration- Klasse, die wir anpassen können, wie im nächsten Abschnitt erläutert.

Die obige Klasse enthält diese Bohnen:

  • Decoder - ResponseEntityDecoder , der SpringDecoder umschließt und zum Decodieren der Antwort verwendet wird
  • Encoder - SpringEncoder , der zum Codieren des RequestBody verwendet wird
  • Logger - Slf4jLogger ist der von Feign verwendete Standardlogger
  • Vertrag - SpringMvcContract , der die Verarbeitung von Anmerkungen ermöglicht
  • Feign-Builder - HystrixFeign.Builder zum Erstellen der Komponenten
  • Client - LoadBalancerFeignClient oder Standard-Feign-Client

4.1. Benutzerdefinierte Bohnenkonfiguration

Wenn Sie eine oder mehrere dieser Beans anpassen möchten, können Sie sie mithilfe einer @ Configuration- Klasse überschreiben , die wir dann der FeignClient- Annotation hinzufügen :

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

In diesem Beispiel weisen wir Feign an, OkHttpClient anstelle des Standardprogramms zur Unterstützung von HTTP / 2 zu verwenden.

Feign unterstützt mehrere Clients für verschiedene Anwendungsfälle, einschließlich des ApacheHttpClient , der mehr Header mit der Anforderung sendet, z. B. Content-Length, die einige Server erwarten.

Um diese Clients zu verwenden, vergessen wir nicht, die erforderlichen Abhängigkeiten zu unserer Datei pom.xml hinzuzufügen , zum Beispiel:

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

Wir können die neuesten Versionen von feign-okhttp und feign-httpclient auf Maven Central finden.

4.2. Konfiguration mit Eigenschaften

Anstatt eine @ Configuration- Klasse zu verwenden, können wir Anwendungseigenschaften verwenden, um Feign-Clients zu konfigurieren , wie in diesem Beispiel für application.yaml gezeigt :

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

Mit dieser Konfiguration setzen wir die Zeitüberschreitungen für jeden deklarierten Client in der Anwendung auf 5 Sekunden und die Protokollierungsstufe auf Basic .

Schließlich können wir die Konfiguration mit dem Standard als Clientnamen erstellen , um alle @ FreeClient- Objekte zu konfigurieren , oder wir können den vorgetäuschten Clientnamen für eine Konfiguration deklarieren:

feign: client: config: jplaceholder:

Wenn sowohl die @ Configuration Bean- als auch die Konfigurationseigenschaften vorhanden sind, überschreiben die Konfigurationseigenschaften die @ Configuration- Werte.

5. Abfangjäger

Das Hinzufügen von Abfangjägern ist eine weitere nützliche Funktion von Feign.

Die Interceptors können für jede HTTP-Anforderung / Antwort eine Vielzahl impliziter Aufgaben ausführen, von der Authentifizierung bis zur Protokollierung.

In diesem Abschnitt implementieren wir unseren eigenen Interceptor und verwenden den von Spring Cloud OpenFeign bereitgestellten. Beide fügen jeder Anforderung einen grundlegenden Authentifizierungsheader hinzu .

5.1. Implementieren von RequestInterceptor

Im folgenden Snippet implementieren wir unseren benutzerdefinierten Anforderungs-Interceptor:

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

Um den Interceptor zur Anforderungskette hinzuzufügen, müssen wir diese Bean nur zu unserer @ Configuration- Klasse hinzufügen oder, wie wir zuvor gesehen haben, in der Eigenschaftendatei deklarieren:

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

5.2. Verwenden von BasicAuthRequestInterceptor

Alternativ können wir die BasicAuthRequestInterceptor- Klasse verwenden, die Spring Cloud OpenFeign bereitstellt:

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

So einfach ist das! Jetzt enthalten alle Anforderungen den grundlegenden Authentifizierungsheader.

6. Hystrix-Unterstützung

Feign unterstützt Hystrix. Wenn wir es aktiviert haben, können wir das Fallback-Muster implementieren.

Mit dem Fallback-Muster führt der Service-Consumer einen alternativen Codepfad aus, um zu versuchen, die Aktion auf andere Weise auszuführen, wenn ein Remote-Service-Aufruf fehlschlägt, anstatt eine Ausnahme zu generieren.

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"); } } }

Dann müssen wir, wie zuvor, den Standard- ErrorDecoder ersetzen, indem wir der @ Configuration- Klasse eine Bean hinzufügen :

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

9. Fazit

In diesem Artikel haben wir Spring Cloud OpenFeign und seine Implementierung in einer einfachen Beispielanwendung erläutert.

Darüber hinaus haben wir gesehen, wie Sie einen Client konfigurieren, Interceptors zu unseren Anforderungen hinzufügen und Fehler mit Hystrix und ErrorDecoder behandeln.

Wie üblich sind alle in diesem Tutorial gezeigten Codebeispiele auf GitHub verfügbar.