Java >> Java Tutorial >  >> Tag >> Spring

Spring WebClient vs. RestTemplate – Vergleich und Funktionen

Einführung

Mit Spring 5 wurde ein neuer reaktiver Webclient namens WebClient eingeführt. In diesem Beitrag werde ich zeigen, wann und wie wir Spring WebClient vs. RestTemplate verwenden können. Ich werde auch beschreiben, welche Funktionen WebClient bietet.

Was ist RestTemplate?

RestTemplate ist eine zentrale Spring-Klasse, die den HTTP-Zugriff von der Client-Seite ermöglicht. RestTemplate bietet POST-, GET-, PUT-, DELETE-, HEAD- und OPTIONS-HTTP-Methoden. Der einfache Anwendungsfall von RestTemplate ist die Nutzung von Restful-Webdiensten.

Sie können eine Bean erstellen, die die Instanz von RestTemplate bereitstellt. Sie können dann @autowire diese Bean in jeder Klasse, in der Sie REST-Dienste aufrufen möchten. RestTemplate ist die Klasse, die die Schnittstelle RestOperations implementiert .

Der folgende Code zeigt die Deklaration der Bean:

    @Bean
    public RestOperations restOperations()
    {
        return new RestTemplate();
    }

Der folgende Code zeigt einen REST-Client „YelpClient“, der die REST-API von Yelp aufruft, um Bewertungen von Mietobjekten zu erhalten.

   @Autowired
   private final RestOperations restOperations;

   public List getRentalPropertyReviews(String address)
   {
        String url = buildRestUrl(businessId);
        HttpHeaders httpHeaders = new HttpHeaders();
        String apiKey = getApiKey(YELP);
        httpHeaders.add("Authorization","Bearer " + apiKey);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity entity = new HttpEntity("parameters", httpHeaders);
        ResponseEntity response;

        try
        {
            response = restOperations.exchange(url, HttpMethod.GET,entity, String.class);
        }
        catch(RestClientException e)
        {
            throw new RuntimeException("Unable to retrieve reviews", e);
        }

    }

Im obigen Code erstellen wir HTTP-Header, indem wir den REST-API-Schlüssel von Yelp als Teil der Autorisierung hinzufügen. Wir rufen die GET-Methode auf, um Bewertungsdaten abzurufen.

Im Grunde muss man tun

  • Autowire das RestTemplate-Objekt
  • HTTP-Header mit Autorisierung und Inhaltstyp erstellen
  • Verwenden Sie HttpEntity, um das Anforderungsobjekt einzuschließen
  • Geben Sie die URL, die HTTP-Methode und den Rückgabetyp für die Austauschmethode an.

Was ist WebClient?

Spring 5 führte einen reaktiven Webclient namens WebClient ein. Es ist eine Schnittstelle zum Ausführen von Webanfragen. Es ist Teil des reaktiven Webmoduls von Spring. WebClient wird RestTemplate irgendwann ersetzen.

Am wichtigsten ist, dass WebClient reaktiv, nicht blockierend, asynchron ist und über das HTTP-Protokoll Http/1.1 funktioniert.

Um WebClient zu verwenden, muss man tun

  • Erstellen Sie eine Instanz von WebClient
  • Stellen Sie eine Anfrage an den REST-Endpunkt
  • Antwort bearbeiten

   WebClient webClient = WebClient
       .builder()
       .baseUrl("https://localhost:8443")
       .defaultCookie("cookieKey", "cookieValue")
       .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 
       .defaultUriVariables(Collections.singletonMap("url", "https://localhost:8443"))
       .build();

Der obige Code zeigt eine Möglichkeit, WebClient zu instanziieren. Sie können auch eine Instanz erstellen, indem Sie einfach WebClient webClient = WebClient.create(); verwenden

WebClient bietet zwei Methoden exchange und retrieve . exchange -Methode ruft normalerweise die Antwort zusammen mit Status und Headern ab. retrieve -Methode ruft den Antworttext direkt ab. Es ist einfacher zu verwenden.

Je nachdem, ob Sie versuchen, ein einzelnes Objekt als Antwort oder eine Liste von Objekten abzurufen, können Sie mono verwenden oder flux .

this.webClient =
                webClientBuilder.baseUrl("http://localhost:8080/v1/betterjavacode/").build();

this.webClient.get()
                .uri("users")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(UserDto.class).collectList();

Der obige Code verwendet grundsätzlich webClient um eine Benutzerliste von der REST-API abzurufen.

Spring WebClient vs. RestTemplate

Wir kennen bereits den entscheidenden Unterschied zwischen diesen beiden Merkmalen. WebClient ist ein nicht blockierender Client und RestTemplate ist ein blockierender Client.

RestTemplate verwendet die Java-Servlet-API unter der Haube. Die Servlet-API ist ein synchroner Aufrufer. Da er synchron ist, blockiert der Thread, bis der Webclient auf die Anfrage antwortet.

Folglich werden Anfragen, die auf Ergebnisse warten, zunehmen. Dies führt zu einer Erhöhung des Arbeitsspeichers.

Andererseits ist WebClient ein asynchroner, nicht blockierender Client. Es verwendet das reaktive Framework von Spring unter der Haube. WebClient ist ein Teil des Spring-WebFlux-Moduls.

Spring WebFlux verwendet eine Reaktorbibliothek. Es liefert Mono und Flux API, um Datensequenzen zu bearbeiten. Reactor ist eine reaktive Streams-Bibliothek. Und alle seine Operatoren unterstützen nicht blockierenden Gegendruck.

Beispiel für die Verwendung von WebClient in einer Spring Boot-Anwendung

Wir können die Fähigkeiten von Spring Web MVC und Spring WebFlux kombinieren. In diesem Abschnitt werde ich eine Beispielanwendung erstellen. Diese Anwendung ruft eine REST-API mit WebFlux auf und wir erstellen eine Antwort, um eine Webseite mit einer Liste von Benutzern anzuzeigen.

RestController für dieses Beispiel ist eine API, um eine Liste von Benutzern zu erhalten:

package com.betterjavacode.webclientdemo.controllers;

import com.betterjavacode.webclientdemo.dto.UserDto;
import com.betterjavacode.webclientdemo.managers.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("v1/betterjavacode")
public class UserController
{
    @Autowired
    public UserManager userManager;

    @GetMapping(value = "/users")
    public List getUsers()
    {
        return userManager.getAllUsers();
    }
}

Controller Klasse, die einen WebClient zum Aufrufen der REST-API verwendet, sieht wie folgt aus:

package com.betterjavacode.webclientdemo.controllers;

import com.betterjavacode.webclientdemo.clients.UserClient;
import com.betterjavacode.webclientdemo.dto.UserDto;
import com.betterjavacode.webclientdemo.managers.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@Controller
public class MainController
{
    @Autowired
    UserClient userClient;

    @GetMapping(value = "/")
    public String home()
    {
        return "home";
    }

    @GetMapping(value = "/users")
    public String getUsers(Model model)
    {
        List users = userClient.getUsers().block();

        model.addAttribute("userslist", users);
        return "users";
    }
}

Nun, der wichtige Codeabschnitt von UserClient ist, wo wir WebClient verwenden werden, um die REST-API aufzurufen.

package com.betterjavacode.webclientdemo.clients;

import com.betterjavacode.webclientdemo.dto.UserDto;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@Service
public class UserClient
{

    private WebClient webClient;

    public UserClient(WebClient.Builder webClientBuilder)
    {
        this.webClient =
                webClientBuilder.baseUrl("http://localhost:8080/v1/betterjavacode/").build();
    }

    public Mono<List> getUsers()
    {
        return this.webClient.get()
                .uri("users")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(UserDto.class).collectList();
    }
}

Der obige Code zeigt, wie zuerst der WebClient erstellt und dann verwendet wird, um die Antwort von der REST-API abzurufen. retrieve -Methode bietet zwei Optionen von mono oder flux . Da wir mehr als einen Benutzer bekommen müssen, verwenden wir flux .

Dies zeigt, dass wir einen reaktiven, nicht blockierenden WebClient verwenden können, der Teil von WebFlux im Spring Web MVC-Framework ist.

Was gibt es sonst noch im Spring WebClient?

Spring WebClient ist Teil von Spring WebFlux Rahmen. Der Hauptvorteil dieser API besteht darin, dass sich der Entwickler nicht um Parallelität oder Threads kümmern muss. Darum kümmert sich WebClient.

WebClient verfügt über eine integrierte HTTP-Client-Bibliotheksunterstützung, mit der Anforderungen ausgeführt werden können. Dazu gehört Apache HttpComponents , Jetty Reactive HttpClient , oder Reaktor Netty .

WebClient.builder() bietet folgende Optionen:

  • uriBuilderFactory – angepasst uriBuilderFactory um die Basis-URL zu verwenden
  • defaultHeader – Header für jede Anfrage
  • defaultCookie – Cookies für jede Anfrage
  • defaultRequest – Um jede Anfrage anzupassen
  • filter – Kundenfilter für jede Anfrage
  • exchangeStrategies – Anpassungen des HTTP-Nachrichtenlesers/-schreibers

Ich habe bereits retrieve gezeigt -Methode in der obigen Code-Demo.

WebClient bietet auch eine Methode exchange an mit Varianten wie exchangeToMono und exchangeToFlux .

Mit attribute() , können wir der Anfrage auch Attribute hinzufügen.

Alternativ kann man WebClient verwenden auch für synchronen Einsatz. In meinem obigen Beispiel MainController , verwende ich block um das Endergebnis zu erhalten. Dies blockiert grundsätzlich parallele Aufrufe, bis wir das Ergebnis erhalten.

Eine Schlüsselfunktion, die WebClient Angebote ist retryWhen() . Für ein widerstandsfähigeres System ist dies eine großartige Funktion, die Sie hinzufügen können, während Sie WebClient verwenden .

        webClient
            .get()
            .uri(String.join("", "/users", id))
            .retrieve()
            .bodyToMono(UserDto.class)
            .retryWhen(Retry.fixedDelay(5, Duration.ofMillis(100)))
            .block();

retryWhen dauert Retry Klasse als Parameter.

WebClient bietet auch eine Funktion zur Fehlerbehandlung. doOnError() ermöglicht Ihnen, den Fehler zu behandeln. Es wird ausgelöst, wenn Mono mit einem Fehler endet. onErrorResume() ist ein Fallback basierend auf dem Fehler.

Schlussfolgerung

In diesem Beitrag habe ich gezeigt, was Spring WebClient ist, wie wir Spring WebClient im Vergleich zu RestTemplate verwenden können und welche verschiedenen Funktionen es bietet.

Wenn Ihnen dieser Beitrag gefallen hat, können Sie hier meinen Blog abonnieren.

Referenzen

  1. Spring WebClient – ​​Spring-Dokumentation
  2. WebClient-Cheatsheet – Spring WebClient

Java-Tag