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, że 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 ręcznie 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
🧨 Nadal 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 ręcznie 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
🧨 Nadal 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ę, za pomocą 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 każdego requestu.
Możesz tam pobierać informacje z requestu, który przyszedł do Twojej aplikacji, z kontekstu Security, z konfiguracji czy nawet generować je losowo.
✅ Masz pełną kontrolę. Biblioteka nic Ci nie narzuca!
Dodaj komentarz