Spring Web MVC, potocznie zwany jako Spring MVC to potężny framework webowy stanowiący jedną ze składowych całego Spring Framework-a.
W zasadzie nie było by w tym żadnej przesady gdybyśmy powiedzieli, że aby w pełni wyczerpać temat Spring-a MVC,
powinniśmy tutaj napisać całkiem sporą książkę (oczywiście z obrazkami ;)).
Niemniej naszym celem jest przedstawienie wiedzy tak, aby zaprezentować najważniejsze i zarazem najczęściej używane elementy frameworka,
a co za tym idzie, przekazać kluczową wiedzę, która umiejętnie wykorzystana pozwoli Wam na napisanie aplikacji webowej na wzór aplikacji StartAPPa.
I właśnie w tym celu zapoznamy się teraz z najważniejszymi aspektami omawianego frameworka.
Dodatkowo niektóre z poniższych punktów znajdują swoje rozwinięcie w innych podstronach naszego kursu. Niezwykle ważne jest aby odwiedzić wszystkie z nich.
Kluczowe funkcjonalności Spring MVC:
-
Dyspozytor Serwletu (DispatcherServlet)
Zanim poznaliśmy Springa byliśmy przyzwyczajeni do tego, że w aplikacji webowej mamy do czynienia z wieloma serwletami, wydawało się to standardem.
Od kiedy pojawił się Spring przekonaliśmy się, że aplikacje webowe można budować w oparciu o jeden serwlet wraz z jego "zarządcą" nazywanym
dyspozytorem. DispatcherServlet, bo o nim mowa, udostępnia wspólny algorytm przetwarzania żądań, podczas gdy rzeczywistą pracę wykonuje konfigurowalny komponent delegatów.
Zgodnie ze specyfikacją serwletów DispatcherServlet musi zostać zadeklarowany i zmapowany za pomocą konfiguracji Java bądź w pliku web.xml.
I teraz uwaga! Korzystając ze Spring Boot-a z szablonem startowym spring-boot-starter-web nie musimy posiadać pliku web.xml,
ani dodatkowej konfiguracji w Javie. Wystarczy, że dodamy spring-boot-starter-web do naszego projektu, a Spring sam będzie wiedział o co nam chodzi. Zgodnie z hasłem "Keep it simple". I to jest to co lubimy!
-
Mapowanie żądań (Request Mapping)
Funkcjonalność umożliwia odwzorowanie żądań na konkretne metody kontrolerów. Bazową adnotacją jest tutaj @RequestMapping,
która jeszcze do niedawna była powszechnie używana w projektach (nawet obecnie adnotacja ta ciągle jest potrzebna w niektórych przypadkach, ale o tym później).
Wraz z wersją 4.3 Springa (Wersje Springa)
wprowadzone zostały wygodniejsze w użyciu dedykowane adnotacje opakowujące @RequestMapping:
- @GetMapping - obsługuje żądania wykonywane metodą GET
- @PostMapping - obsługuje żądania wykonywane metodą POST
- @PutMapping - obsługuje żądania wykonywane metodą PUT
- @DeleteMapping - obsługuje żądania wykonywane metodą DELETE
- @PatchMapping - obsługuje żądania wykonywane metodą PATCH
Adnotacje te omawiamy nieco szerzej w artykule: Spring MVC - Mapowanie żądań HTTP
-
Metody obsługi żądań (Handler methods)
Wspomniane wyżej adnotacje spowodują, że żądanie HTTP trafi do właściwej metody zdefiniowanej w odpowiednim kontrolerze. Natomiast w tym miejscu należy zadać pytanie
co się dzieje dalej? Jak dobrać się do danych, które zostały wysłane w ramach żądania? Odpowiedź polega na przedstawieniu kilku innych elementów funkcjonujących w Springu,
które wspierają programistę w uzyskiwaniu dostępu do danych. Mowa tu o adnotacjach, które możemy stosować w obrębie metod oznaczonych adnotacjami typu @RequestMapping i
które można podzielić na dwie kategorie: argumenty metod oraz zwracane wartości metod. Oto najczęściej używane z nich:
Argumenty metod
- @RequestParam - obsługuje parametr typu query param (parametry nazwane w ścieżce: "?nazwa_parametru=wartosc")
- @PathVariable - obsługuje parametr typu path param (poprzez szablonowe zmienne URI: "/{nazwa_zmiennej}")
- @RequestBody - obsługuje body żądania (konwertuje zawartość body żądania HTTP do konkretnego typu argumentu metody)
- @RequestPart - obsługuje obiekt "w częściach" (dostęp do części w ramach żądania multipart/form-data)
Zwracane wartości metod
- @ResponseBody - obsługuje body odpowiedzi (konwertuje typ argumentu do body odpowiedzi HTTP)
Adnotacje te omawiamy szerzej w artykule: Spring MVC - Metody obsługi żądań HTTP
-
Obsługa wyjątków (Exceptions handling)
Nie byłoby frameworka MVC bez obsługi błędów (tak jak nie byłoby projektów IT, gdyby dla każdego z nich nie działał dedykowany - choćby skromny - support team rozwiązujący zgłaszane problemy).
Jakie zatem błędy mogą się pojawić na naszej drodze podczas pracy z aplikacją? W zasadzie dowolne. Od błędów natury programistycznej po błędy w interpretacji żądań, problemy
z wysyłanymi parametrami, czy też np. z autentykacją w systemie, bądź autoryzacją w dostępie do jego zasobów.
Wszystkie takie problematyczne sytuacje wypadało by obsłużyć i właśnie
po to została stworzona w Springu adnotacja @ExceptionHandler, która służy do oznaczania metod odpowiedzialnych za odpowiednią obsługę błędów.
Możemy definiować handlery per kontroler albo też zbiorczo dla grupy kontrolerów. O tym jednak już w następnym punkcie.
-
Porady dla kontrolerów (Controller Advice)
Funkcjonalności takie jak np. obsługa błędów za pomocą annotacji @ExceptionHandler mogą być zrealizowane przekrojowo
dla wszystkich (lub wybranych) kontrolerów w naszej aplikacji. Jeśli zatem chcemy wprowadzić jeden spójny model obsługi wyjątków dla całej aplikacji,
to możemy w tym celu stworzyć klasę opisaną adnotacją @ControllerAdvice. Taka klasa pozwoli nam na zdefiniowanie metod
opisanych adnotacją @ExceptionHandler, gdzie każda z tych metod będzie odpowiedzialna za dostarczenie odpowiedniej obsługi
dla przechwytywanego typu wyjątku.
Nasza rekomendacja
W artykule wspomnieliśmy o tym, że nie potrzebujemy używać web.xml w naszych projektach.
Trzeba jednak pamiętać, że czasem zdarzają się sytuacje, w których chcemy np. posiadać dynamiczną konfigurację w postaci takiego pliku, aby zmieniać coś bez potrzeby
redeployowania aplikacji. Nic nie stoi więc na przeszkodzie abyśmy więc takiego pliku używali.
Dodatkowo warto wspomnieć, że używanie pliku web.xml może iść w parze z razem ze Spring Boot-em. Możemy budować projekt całkowicie oparty o Spring Boota,
do którego na etapie wdrażania dołączamy
odpowiednio skonfigurowany plik web.xml.
Tak zresztą działa aplikacja StartAPPa i takie rozwiązanie zalecamy.
Na etapie developmentu, Spring Boot zapewnia nam wiele uproszczeń i udogodnień (np. wbudowany Tomcat plus startery), a war który w ten sposób przygotowujemy możemy
i tak później zdeployować w kontenerze aplikacji, np. na zewnętrznym Tomcacie.
Używamy w StartAPPa
Wszystkie kursy Spring oparte są u nas Spring Boota i zawierają szablon startowy
spring-boot-starter-web, co powoduje, że
z automatu otrzymujemy funkcjonalności frameworka Spring MVC. Wielokrotnie używamy adnotacji takich jak
@GetMapping,
@PostMapping,
czy też
@PathVariable itp... Za przykład niech posłuży tu choćby klasa
ItemController:
Oczywiście, zgodnie z tym co pisaliśmy w bieżącym rozdziale, w każdym kursie znajdziecie również klasę zarządzającą obsługą wyjątków
CustomExceptionHandler,
która korzysta z porady
@ControllerAdvice.
Linki
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc
http://spring.io/projects/spring-boot