Jak z głową zbudować własną libkę

effectivedev.pl 2 lat temu

Tworzenie własnej libki na potrzeby architektury mikroserwisowej to nie jest najlepszy pomysł. Z wielu powodów. Tym razem spójrz jak to zrobić, w sytuacji, kiedy jednak taką libke bardzo chcesz stworzyć.

Weźmy na warsztat taką sytuację:

“Komunikacja REST wymaga dodania nagłówków X, Y i Z.”

Masz wiele mikroserwisów i wszędzie te nagłówki muszą być wysyłane.

No to teraz, na przykładzie WebClienta, przejdźmy od najgorszego do najlepszego rozwiązania

Skonfigurowany WebClient

Twoja libka dostarcza gotowego WebClienta. Wystarczy, iż go użyjesz u siebie, aby wykonać zapytanie REST, wszystkie nagłówki są magicznie dołączone.

@Configuration public class WebClientConfig { @Bean WebClient webClient() { return WebClient.builder() .defaultHeader("x-header-x", "some-value-x") .defaultHeader("x-header-y", "some-value-y") .defaultHeader("x-header-z", "some-value-z") .build(); } }

Po podniesieniu takie klasy konfiguracyjnej będziesz mieć gotowego do użycia WebClienta. Niby super. Ale…

Nie masz możliwości dodania kolejnych nagłówków.

Nie masz możliwości dodania filtrów.

Nie masz możliwości wpłynięcia na konfigurację serializacji (Jackson).

Twoja aplikacja musi być w pełni zgodna z założeniami libki, co do tego jak “pobrać” wartości dla nagłówków.

Generalnie nic nie możesz, jak chcesz coś zmienić, musisz zrobić wszystko manualnie od nowa.

Skonfigurowany WebClient.Builder

Trochę bardziej elastycznym rozwiązaniem, będzie dostarczenie prekonfigurowanego WebClient.Buildera.

@Configuration public class WebClientConfig { @Bean WebClient.Builder webClientBuilder() { return WebClient.builder() .defaultHeader("x-header-x", "some-value-x") .defaultHeader("x-header-y", "some-value-y") .defaultHeader("x-header-z", "some-value-z"); } }

Wykorzystując go, możesz stworzyć WebClienta, jednocześnie dodając swoje customizacje.

Możesz dodać kolejne nagłówki

Możesz dodać filtry

Możesz dowolnie konfigurować serializacje

przez cały czas Twoja aplikacja musi być w pełni zgodna z założeniami libki.

Automagiczny filtr

Jeżeli masz ochotę na jeszcze większą elastyczność, to warto pójść w stronę własnego filtra. Dzięki temu masz dodatkowo kontrolę na tym, kiedy te nagłówki zostaną nadane.

public class MyCustomHeadersFilter implements ExchangeFilterFunction { @Override public Mono<ClientResponse> filter( ClientRequest request, ExchangeFunction next) { var headers = request.headers(); headers.add("x-header-x", "some-value-x"); headers.add("x-header-y", "some-value-y"); headers.add("x-header-z", "some-value-z"); return next.exchange(request); } }

Taki filtr manualnie dodajesz, w wybrane przez siebie miejsce podczas tworzenia WebClienta w swojej apce. Nikt nic Ci automatycznie nie konfiguruje.

Masz pełną kontrolę nad Twoim WebClientem

Ty decydujesz w którym momencie zostaną dodane nagłówki

przez cały czas Twoja aplikacja musi być zgodna z założeniami libki. Filtr musi skądś wartości nagłówków pobrać.

Filtr z Supplierem

Aby uwolnić się od ostatniego problemu, musisz po prostu zparametryzować filtr!

@RequiredArgsConstructor public class MyCustomHeadersFilter implements ExchangeFilterFunction { private final Supplier<HeaderValues> valuesSupplier; @Override public Mono<ClientResponse> filter( ClientRequest request, ExchangeFunction next) { var headers = request.headers(); var values = valuesSupplier.get(); headers.add("x-header-x", values.getX()); headers.add("x-header-y", values.getY()); headers.add("x-header-z", values.getZ()); return next.exchange(request); } }

Teraz, dodając filtr do swojego WebClienta, musisz przekazać mu tez funkcję, dzięki której zostaną dostarczone odpowiednie wartości z Twojej aplikacji. Masz pełną kontrolę nad tym, co tam przekażesz, a wartość będzie za każdym razem pobierana od nowa, dla wszystkich requestu.

Możesz tam pobierać informacje z requestu, który przyszedł do Twojej aplikacji, z kontekstu Security, z konfiguracji czy choćby generować je losowo.

Masz pełną kontrolę. Biblioteka nic Ci nie narzuca!

Idź do oryginalnego materiału