W rozdziale
Spring Framework - Spring MVC
wspominamy, że po otrzymaniu żądania HTTP framework MVC musi wiedzieć, w jaki sposób takie żądanie ma zostać obsłużone.
Po dopasowaniu ścieżki i wybraniu odpowiedniej metody Java (zgodnie z opisem
Spring MVC: Mapowanie requestów HTTP),
Spring przestępuje do analizy adnotacji umieszczonych w obrębie tej metody.
I tu od razu uwaga. Pełna specyfikacja Springa MVC załączona w postaci linka na dole strony, zawiera większą ilość adnotacji,
niż te opisywane przez nas. Wynika to z tego, że nie chcemy robić przedruku z oficjalnej dokumentacji, lecz wolimy skupić się
na tym co jest najczęściej używane i te elementy opisać nieco dokładniej wraz z przykładami. Oczywiście zachęcamy również do odwiedzania zewnętrznych linków,
gdyż będą one dobrym uzupełnieniem przygotowanego przez nas materiału.
Wracając do tematu adnotacji należy przypomnieć, że dzielimy je na dwie kategorie: argumenty metod oraz zwracane wartości metod. Przedstawiona poniżej lista zawiera
w większości opis adnotacji dotyczących argumentów metod. Ostatnia adnotacja
@ResponseBody dotyczy zwracanej wartości:
-
Adnotacja @RequestParam
Adnotacja jest stosowana w przypadku, gdy wysyłamy żądanie ustawiając w ścieżce nazwę parametru z wartością, np.:
HTTP GET: http://.../users?id=23
Wówczas metodę oznaczamy:
Możemy określić czy parametr zawsze musi być ustawiony. Domyślnie required jest ustawione na true.
W przykładzie wyżej nie podaliśmy w ogóle tego atrybutu (required), więc przyjmuje on wartość domyślną. W przypadku gdybyśmy chcieli ustawić wartość false
zapis wyglądałby w ten sposób:
@RequestParam(value="id", required="false") Long id
-
Adnotacja @PathVariable
Adnotacja jest stosowana w przypadku, gdy wysyłamy żądanie ustawiając wartość parametru bezpośrednio w ścieżce, np.:
HTTP GET: http://.../appaitems/11
Wówczas metodę oznaczamy:
Od Springa w wersji 5 możemy wreszcie określać czy wartosć parametru zawsze musi być ustawiona.
Teoretycznie wersja 4.3 umożliwiała to poprzez użycie Optional z Javy 8, niemniej obecnie mamy ten atrybut wbudowany już bezpośrednio w adnotację.
Domyślnie required jest ustawione na true.
W przykładzie wyżej nie podaliśmy w ogóle tego atrybutu (required), więc przyjmuje on wartość domyślną. W przypadku gdybyśmy chcieli ustawić wartość false
zapis wyglądałby w ten sposób:
@PathVariable(value="id", required="false") Long id
-
Adnotacja @RequestBody
Adnotacja jest stosowana w przypadku, gdy przesyłamy dane w body żądania. Wtedy tworzymy obiekt, którego pola muszą zgadzać się
z polami w wysyłanym obiekcie. Zgodnie z obowiązującymi trendami w większości przypadków będzie to obiekt JSON.
Wysyłając żądanie na ścieżkę:
HTTP POST: https://.../password/token
wysyłamy tak naprawdę JSON-a (jako ciało wiadomości):
W tym momencie Spring wykonuje konwersję do obiektu Java (adnotacja @NotNull nie ma tu związku - uczestniczy w walidacji pola):
Ostatecznie w metodzie kontrolera otrzymamy obiekt TokenRequestDTO wraz z wypełnionym polem email:
W kontekście omawianych operacji adnotacja @Valid nie ma związku - jest dodana jedynie
w celu sprawdzenia poprawności pola (email nie może być pusty).
-
Adnotacja @RequestPart
Adnotacja również jest stosowana w przypadku, gdy przesyłamy dane w body żądania.
Natomiast różnica polega na tym, że używamy jej w kontekście żądań określonych jako multipart/form-data.
Powoduje to, że jest użyteczna w przypadku przesyłania na serwer plików, np. zdjęć.
Dodatkowo jeśli razem ze zdjęciem chcemy przesłać obiekt, który jest JSON-em (np. z metadanymi zdjęcia), wówczas jego też określamy adnotacją
@RequestPart i podobnie jak w przypadku @RequestBody tworzymy obiekt, którego pola muszą zgadzać się
z polami w wysyłanym obiekcie JSON.
Dla tej adnotacji również możemy określić czy parametr zawsze musi być ustawiony. Domyślnie required jest ustawione na true.
Jak widać my umożliwiamy w tym przykładzie wysłanie żądania również bez załączonego zdjęcia.
-
Adnotacja @ResponseBody
Adnotacja jest stosowana w przypadku, gdy chcemy zwrócić serializowane dane (obiekty sprowadzone do postaci binarnej)
z metody kontrolera (choć nie tylko kontrolera, ale o tym za chwilę).
Natomiast jeśli wszystkie nasze metody w danym kontrolerze mają zwracać tylko i wyłącznie dane serializowane,
wówczas możemy skorzystać z adnotacji @RestController. Ta meta-adnotacja łączy w sobie
adnotacje @Controller oraz @ResponseBody.
Podobnie sprawa wygląda z klasami oznaczonymi adnotacją @ControllerAdvice.
W tym przypadku również jeśli w klasie wszystkie metody mają zwracać dane serializowane, to możemy użyć meta-adnotacji łączącej
adnotacje @ControllerAdvice oraz @ResponseBody.
Użyjemy wtedy adnotacji o nazwie @RestControllerAdvice.
W dalszym ciągu możemy jednak używać adnotacji @ResponseBody w czystej postaci,
jeśli nie mamy takiego komfortu, że wszystkie metody mogą być nią opatrzone automatycznie.
Wtedy użyjemy jej tylko tam gdzie tego potrzebujemy.
W powyższym przykładzie używamy tej adnotacji w klasie porady dla kontrolerów (@ControllerAdvice), w której obsługujemy różne rodzaje błędów
w aplikacji.
Rekomendacja
W zasadzie to od czego należałoby zacząć, to od zwrócenia uwagi, że umiejętność użycia wszystkich wyżej wymienionych adnotacji jest absolutnym must-have
w trakcie pracy ze Springiem, szczególnie w kontekście programowania aplikacji webowych opartych o styl REST. Należy zatem bardzo dobrze to opanować.
Ciekawostką jest fakt, że ze wszystkich tych adnotacji najrzadziej spotykamy w projektach pierwszą z nich, a więc @RequestParam.
Wynika to pewnie z tego, że albo w systemach potrzebujemy przesyłać duże ilości parametrów naraz (np. dane formularza) i robimy to w body wiadomości, albo też jeśli już wymagane jest użycie
pojedyńczych parametrów (np. przy pobieraniu obiektu po id), to zgodnie z REST wykonujemy to poprzez stosowanie parametrów ścieżki @PathVariable.
Praktyka
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Czy informacje, które otrzymałeś, były pomocne?
Jeśli tak, zapraszam Cię do podarowania mi kawy.
Topowe Materiały
Spring IO: Mapping Requests
Baeldung: Spring Web Annotations
Baeldung: Guide to Spring Handler Mappings
Baeldung: Spring RequestMapping
Udemy: [NEW] Spring Boot 3, Spring 6 & Hibernate for Beginners — polskie napisy