Mapowanie żądań to bardzo ważna funkcjonalność,
umożliwiająca skierowanie przetwarzania żądań HTTP do odpowiednich metod w języku Java. Aby to osiągnąć, niezbędne
są informacje o ścieżce (path), na którą skierowano żądanie, oraz o typie metody HTTP użytej podczas jego wysyłania.
Te dane pozwalają frameworkowi na precyzyjne dopasowanie żądania do właściwej metody obsługującej, zapewniając tym
samym efektywne i zorganizowane przetwarzanie żądań w aplikacjach webowych.
Adnotacje mapujące
Zgodnie z tym co opisujemy w tekście
Starter REST,
wyróżniamy kilka metod, które uczestniczą w obsłudze żądań. Najważniejsze z nich to: GET, PUT, POST, DELETE. To właśnie one muszą znaleźć swoje odpowiedniki
po stronie frameworka, aby Spring mógł uruchomić właściwą metodę. Jak wiążemy metody Java z konkretnymi metodami HTTP?
Używamy w tym celu adnotacji, których lista wygląda następująco:
-
Adnotacja @GetMapping
Dawniej, przed Springiem w wersji 4.3 adnotacja występowała tylko pod postacią:
@RequestMapping(method = RequestMethod.GET)
Obecnie adnotacja ta jest częścią adnotacji @GetMapping, której użycie powoduje że kod jest nieco bardziej przejrzysty (wspominamy o tym nieco szerzej w dalszej części rozdziału).
Adnotacją oznaczamy metodę, która ma przyjąć nasze żądanie GET, np.:
Jak widać adnotacja @GetMapping przyjmuje jako parametr value ścieżkę, którą framework dopasowuje
do ścieżki (path), na którą zotało wysłane żądanie. Jeśli ścieżki się zgadzają następuje uruchomienie metody i wykonanie jej kodu.
Reasumując, jeśli wysłaliśmy na serwer (na którym działa Spring MVC) żądanie HTTP za pomocą metody HTTP GET oraz zdefiniowaliśmy URL tego żądania, na przykład:
"/image/17/obrazek.jpg", to wówczas Spring przechwyci takie żądanie i uruchomi metodę getImage.
Co oznacza adnotacja @PathVariable oraz jak interpretować fragment mapowania ścieżki "/{appaItemId}/{imageName:.+}" ?
Zainteresowanych odpowiedzią na to pytanie zapraszamy do rozdziału Spring MVC - Mapowanie danych w requestach HTTP.
-
Adnotacja @PostMapping
Dawniej:
@RequestMapping(method = RequestMethod.POST)
Obecnie adnotacja ta jest częścią adnotacji @PostMapping.
Adnotacją oznaczamy metodę, która ma przyjąć nasze żądanie POST, np.:
Jak widać adnotacja @PostMapping również przyjmuje jako parametr value ścieżkę, którą framework dopasowuje
do ścieżki (path), na którą zotało wysłane żądanie. Tak samo jak w przypadku adnotacji @GetMapping jeśli ścieżki się zgadzają następuje uruchomienie metody i wykonanie jej kodu.
Podobnie będzie to wyglądać dla pozostałych adnotacji.
O adnotacji @RequestParam piszemy w rozdziale Spring MVC - Mapowanie danych w requestach HTTP.
-
Adnotacja @PutMapping
Dawniej:
@RequestMapping(method = RequestMethod.PUT)
Obecnie adnotacja ta jest częścią adnotacji @PutMapping.
Adnotacją oznaczamy metodę, która ma przyjąć nasze żądanie PUT, np.:
-
Adnotacja @DeleteMapping
Dawniej:
@RequestMapping(method = RequestMethod.DELETE)
Obecnie adnotacja ta jest częścią adnotacji @DeleteMapping.
Adnotacją oznaczamy metodę, która ma przyjąć nasze żądanie DELETE, np.:
-
Adnotacja @PatchMapping
Dawniej:
@RequestMapping(method = RequestMethod.PATCH)
Obecnie adnotacja ta jest częścią adnotacji @PatchMapping.
Adnotacją oznaczamy metodę, która ma przyjąć nasze żądanie PATCH, np.:
O adnotacji @RequestBody piszemy w rozdziale Spring MVC - Mapowanie danych w requestach HTTP.
Składanie ścieżek
Jak już wiesz,
dedykowane adnotacje w pewien sposób poprawiają nasz kod, ponieważ staje się on bardziej przejrzysty.
No dobrze, ale czy możemy się pozbyć całkowicie adnotacji
@RequestMapping?
Okazuje się, że nie, ponieważ nadal będziemy używać tej adnotacji, aby zmapować całą klasę (a nie tylko metodę) naszego kontrolera na konkretną scieżkę.
Zobaczmy rozwinięcie naszego pierwszego przykładu o adnotacji
@GetMapping:
Jak widać adnotacja
@RequestMapping określa ścieżkę w postaci
"/api/appaform/appaimages".
Oznacza to, że Spring próbując dopasować ścieżkę z przychodzącego żądania będzie rozpoczynał dopasowywanie od "neutralnej" adnotacji na klasie,
a później skleji ją ze ścieżką określoną dla adnotacji dedykowanej na metodzie. Jeśli całość będzie się zgadzała, wówczas wybrana metoda zostanie uruchomiona.
Mając teraz wszystkie dane o kontrolerze już wiemy, że jeśli wysłaliśmy na serwer żądanie HTTP za pomocą metody HTTP GET oraz zdefiniowaliśmy URL tego żądania, na przykład:
"/api/appaform/appaimages/image/17/obrazek.jpg", to wówczas Spring przechwyci takie żądanie i uruchomi metodę
getImage.
Metoda HEAD
Na koniec jeszcze jedna kwestia, która z pewnością nie daje żyć czytelnikom dążącym do porządku idealnego. Mowa o braku adnotacji @HeadMapping, która
mogłaby odpowiadać metodzie HTTP HEAD. Dlaczego Spring MVC nie definiuje w ogóle takiej adnotacji?
Otóż zgodnie ze specyfikacją, żądanie HEAD jest podobne do GET, ale nie wymaga od serwera zwracania treści odpowiedzi,
tylko nagłówków. Spring MVC automatycznie obsługuje żądania HEAD dla każdego endpointu zdefiniowanego przez
@GetMapping, co może tłumaczyć brak potrzeby definiowania oddzielnej adnotacji @HeadMapping. Mimo to, można
argumentować, że wprowadzenie takiej adnotacji mogłoby przyczynić się do większej czytelności w definicjach endpointów.
Rekomendacja
Kluczowym aspektem, na który należy zwrócić uwagę podczas pracy z Spring MVC, jest odpowiedni dobór
metod HTTP oraz związanych z nimi adnotacji, dostosowanych do realizowanego zadania. Zachęcamy do
zapoznania się z ogólnymi zasadami dotyczącymi metod HTTP dostępnymi w sekcji
Starter REST.
Szczególnie polecamy zwrócić uwagę na koncepcję idempotentności. Jest to nie tylko istotny aspekt
przy wyborze odpowiedniej metody HTTP, ale również popularny temat podczas rozmów kwalifikacyjnych.
Zrozumienie i stosowanie tych zasad jest kluczowe dla efektywnego i profesjonalnego tworzenia
aplikacji webowych.
Praktyka
Prawie wszystkie przykłady przytoczone wyżej (poza Patch Mapping) pochodzą z kodu aplikacji.
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