REST-owe żądania w Java Spring z wykorzystaniem RestTemplate

Wraz z wielkim wzrostem dwóch podejść RESTful Web Services oraz mikroserwisów warto jest mieć łatwy sposób na stworzenie odpowiedniej klasy wspomagającej komunikacje miedzy serwisami. W tym wpisie pokażę, jak zrobić to w javowym Springu z wykorzystaniem klasy RestTemplate.

Na początek

  • bardzo podstawowa wiedza o Javie
  • 5 minut

RestTemplate

RestTemplate (implementujace interface RestOperations) to wedlug dokumentacji Springa centralna klasa dla synchronicznego dostępu HTTP. Trochę bardziej ludzkim językiem – w oparciu o tę klasę można łatwo z poziomu kodu Javy wykonywać żądania HTTP. Stwórzmy więc zręby pod własny klient Rest HTTP 🙂

Najprostszy przykład

Zacznijmy od czegoś banalnego. Poniższy kod wykona po prostu request HTTP do wskazanego serwisu. Tu wykorzystam zasoby projektu „dane publiczne” licząc, że

RestTemplate rest = new RestTemplate();
final String url = "http://yarpo.pl/download/test.json"; 
Map<String, Object> res = rest.getForObject(url, Map.class, new HashMap<>());

Już tak prosty fragment kodu pozwala nam na odczytanie zasobu ze wskazanego źródła (zmienna url). Dwa pozostałe argumenty to:

  • klasa, do jakiej chcemy zmapować wynik
  • nagłówki HTTP (tu pusty hash, ale czasem chcemy przesłać np. Content-type itp.)

Po więcej szczegółów odsyłam do dokumentacji.

Celowo dodałem na swoim serwerze plik JSON z taką zawartością:

{"content": "Hello world!", "data": { "date": "2017-06-19", "author": "yarpo" }}

 

Skoro odczytałem już zawartość tego pliku to mogę odczytać zawartość w taki sposób:

String content = res.get("content"); // "Hello world!"

Przyznacie, że póki co idzie bardzo łatwo. Trzeba jednak z bólem przyznać, ze operowanie na obiekcie typu HashMap nie jest najwygodniejsze (i jest koszmarem przy refaktoryzacjach). Gdyby tylko można było to zrzutować do obiektu zdefiniowanej samodzielnie klasy… 😉

Mapowanie wyniku do własnej klasy

W tym przykładzie nadal będę operował na tym samym zasobie (http://yarpo.pl/download/test.json). Napiszmy szybko klasę, która pozwoli nam na mapowanie takiego JSONa do prawidłowego obiektu w Javie.

@JsonIgnoreProperties(ignoreUnknown = true)
public class YarpoRestContent {
    @JsonProperty("content")
    String content;
}

(adnotacje z pakietu: com.fasterxml.jackson.annotation.*)

Teraz możemy nasz kod uczynić bardziej czytelnym:

YarpoRestContent res = rest.getForObject(url, YarpoRestContent.class, new HashMap<>());
res.content; // "Hello world!"

Zagnieżdżone obiekty

Poprzedni przykład klasy YarpoRestContent był koszmarnie banalny. Rozbudujmy go tak, aby móc w instancji takiego obiektu trzymać wszystkie dane pobrane z zasobu:

@JsonIgnoreProperties(ignoreUnknown = true)
public class YarpoRestContent {
    @JsonProperty("content") String content; 
    @JsonProperty("data") Details details; // inna nazwa zmiennej i klucz w JSON
    
    static class Details {
        @JsonProperty("date") LocalDate date; 
        @JsonProperty("author") String author;
    }
}

Jak widać nie zawsze trzeba dawać takie same nazwy zmiennej, jak wartość klucza w obiekcie JSON. W niektórych przypadkach (gdy nazwa pola klasy i klucza w obiekcie JSON sobie odpowiadają) można nawet zrezygnować z adnotacji.

Przesyłanie nagłówków HTTP

Niektóre endpointy, do których będziecie chcieli wysyłać żądania HTTP mogą oczekiwać odpowiednich nagłówków. RestTemplate ma bardzo przyjazny interfejs i do tego:

HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.AUTHORIZATION, "Sezamie otwórz się!");
YarpoRestContent res = rest.getForObject(url, YarpoRestContent.class, headers);

I gotowe. Oczywiście w przypadku nagłówka autoryzacyjnego należy podać poprawny dla danej sesji ciąg znaków :). Można także ustawić dużo więcej nagłówków:

Co dalej

Oczywiście ten artykuł ledwie dotknął wierzchołka góry lodowej. Mam nadzieje jednak, ze pomógł znaleźć proste rozwiązanie problemu.

Jako zadanie domowe zostawię implementację pozostałych metod HTTP. Na pewno przydatna po raz kolejny będzie dokumentacja 🙂

W niedalekiej przyszłości planuję opublikować jeszcze kilka wpisów na ten temat:

  • klasa RestHttpClient – moja implementacja pozwalająca jeszcze szybciej i łatwiej łączyć się z innymi serwisami
  • jak to wszystko testować w junit?

Mam nadzieję, że ze wszystkim się wyrobię 🙂

Jedna odpowiedź do “REST-owe żądania w Java Spring z wykorzystaniem RestTemplate”

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *