Mapowanie żądań to bardzo ważna funkcjonalność, która polega na pokierowaniu frameworka w taki sposób, aby dla danego żądania HTTP, wybrał odpowiednią metodę Java
w celu obsługi tego żądania. Co jest mu do tego potrzebne? Na pewno kluczowymi informacjami są ścieżka (path), na którą zostało wysłane żądanie, jak również rodzaj metody HTTP
zdefiniowanej podczas jego wysyłania.
Adnotacje mapujące
Zgodnie z tym co opisujemy w dziale
Starter,
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:
-
@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 - Metody obsługi żądań HTTP.
-
@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 - Metody obsługi żądań HTTP.
-
@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.:
-
@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.:
-
@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 - Metody obsługi żądań HTTP.
Składanie ścieżek
Pisaliśmy wyżej o tym,
że adnotacje dedykowane 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. Mamy tutaj na myśli kwestię nieobecności na liście adnotacji takiej jak @HeadMapping, która
mogłaby odpowiadać metodzie HTTP HEAD. Dlaczego Spring MVC nie definiuje w ogóle takiej adnotacji? Do końca nie wiadomo, ale z dużym prawdopodobieństwem można stwierdzić, że odpowiedź
na to pytanie jest związana z ogólną definicją określoną dla żądań HEAD, która mówi, że
metoda HEAD jest identyczna jak metoda GET poza tym, że serwer nie może zwracać body wiadomości w odpowiedzi.
Stąd pewnie programiści Springa nie dodali takiej adnotacji, co szczerze mówiąc jednak do nas nie przemawia. Wydaje się, że warto było by dodać tą adnotacje przynajmniej dla utrzymania porządku idealnego :).
Nasza rekomendacja
To na co powinniśmy zwrócić uwagę, to z pewnością odpowiednie dobieranie metod HTTP, a tym samym
adnotacji do realizowanego zagadnienia. Jeśli interesują Was ogólne zasady obowiązujące w pracy z metodami HTTP, to z tego miejsca ponownie zapraszamy do działu
Starter.
Szczególnie polecamy zapoznać się z pojęciem idempotentności. Nie dość, że jest to temat istotny podczas właściwego doboru metod, to jeszcze jest to jeden z ulubionych tematów
podczas rozmów kwalifikacyjnych ;)
Używamy w StartAPPa
Prawie wszystkie przykłady przytoczone wyżej (poza Patch Mapping) pochodzą z kodu aplikacji.
Linki
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping
https://www.w3schools.com/tags/ref_httpmethods.asp