Mapowanie żądań HTTP

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.:
    @GetMapping(value = "/image/{appaItemId}/{imageName:.+}")
    public void getImage(@PathVariable Long appaItemId, 
                            @PathVariable String imageName, ...) throws Exception {
    
        imageLoader.copyImage(imageName, appaItemId, request, response);
    }
    
    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.:
    @PostMapping(value = "/xls")
    public ResponseEntity<Void> importAppaItems(@RequestParam MultipartFile multipartFile)
    		throws Exception {
    
        ...
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
    
    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.:
    @PutMapping("/current/roles/{newRoleName}")
    public ResponseEntity<Void> updateCurrentUserRoleName(@PathVariable("newRoleName") ...
    
        ...
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
    
  • @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.:
    @DeleteMapping("/{appaItemId}")
    public ResponseEntity<Void> delete(@PathVariable Long appaItemId) throws Exception {
    
        appaItemService.deleteAppaItem(appaItemId);
        
        return ResponseEntity.noContent().build();
    }
    
  • @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.:
    @PatchMapping("/{id}")
    public ResponseEntity<Void> updatePart(@RequestBody User userPart, @PathVariable("id") Long id) {
    
        ...
        
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
    


    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:
@RestController
@RequestMapping("/api/appaform/appaimages")
public class ImageController {

    ...
    
    @GetMapping(value = "/image/{appaItemId}/{imageName:.+}")
    public void getImage(@PathVariable Long appaItemId, 
                            @PathVariable String imageName, ...) throws Exception {
    
    	imageLoader.copyImage(imageName, appaItemId, request, response);
    }
}
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 naszych modułów. Dla porządku przedstawiamy kursy w jakich można je znaleźć:

Przykład z adnotacją @GetMapping: Formularz Zaawansowany (wczytywanie obrazków podczas edycji formularza)
Przykład z adnotacją @PostMapping: Importer XLS (przesłanie pliku XLS/XLSX na serwer przez użytkownika)
Przykład z adnotacją @PutMapping: Formularz Podstawowy (zmiana roli użytkownika)
Przykład z adnotacją @DeleteMapping: Tabela Zaawansowana (usunięcie itemu przez użytkownika)
Linki
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping
https://www.w3schools.com/tags/ref_httpmethods.asp

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy:
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .