Przejdź do treści

Spring Boot Web – Przekazywanie zmiennych do aplikacji przez URL czyli użycie @RequestParam i @PathVariable

W poprzednich wpisach pokazałem jak stworzyć prostą aplikację z pomocą Spring Boota. Dzisiaj chciałbym rozszeżyć tamten wpis o temat przekazywania zmiennych do aplikacji używając URL. Zakładam, że wiesz już jak stworzyć podstawowy szkielet działającej aplikacji, jeśli nie to zapraszam do przeczytania wpisu na ten temat pod adresem: http://blog.mloza.pl/spring-boot-szybkie-tworzenie-aplikacji-web-w-javie/.

W pierwszym poście na temat tworzenia aplikacji w Spring Boot pokazywałem jak możemy zmapować adres url na metodę w kontrolerze. Nie wspomniałem wtedy o tym, że możemy również w adresie zawrzeć parametry które mogą być przekazywane do naszej funkcji. Jest to bardzo użyteczne i szeroko wykorzystywane w aplikacjach. Przykładowo, możemy napisać metodę która ma za zadanie wyciągnać zawartość wpisu na blogu z bazy danych. Zamiast tworzyć oddzielne metody dla każdego wpisu i ręcznie je mapować, możemy stworzyć jedną metodę której będziemy przekazywać identyfikator wpisu. Na podstawie tego identyfikatora, metoda znajdzie odpowiedni wpis i zwróci go do przeglądarki.

W poście skupie sią na dwóch metodach przekazywanie danych. Pierwsza to użycie QueryString – jest to część adresu występująca po znaku zapytania, na przykład: http://blog.mloza.pl/przykladowy/url?klucz=wartosc&nazwa=123. Zmienne podajemy w formacie klucz=wartosc, a kolejne elementy oddzielamy znakiem &.

Drugą możliwość przesyłania danych jest umieszczenie ich bezpośrednio w adresie url. Przykładowo: http://blog.mloza.pl/przykladowy/url/wartosc/123. W takim wypadku nie przekazujemy już kluczy, a jedynie wartości.

Kod źródłowy przykładów znajduje się w GitHubie pod adresem: https://github.com/mloza/spring-boot-params

Implementacja w Spring Boot: query string

Zacznijmy od przekazywania parametrów przez query string. Musimy stworzyć metodę na którą będzie mapowany url. Następnie podajemy jako listę parametrów metody wszystkie zmienne których się spodziewamy. Każdy parametr adnotujemy @RequestParam i nadajemy mu nazwę taką jak klucz który będziemy przekazywać podczas uruchomienia aplikacji:

Zacznijmy od przekazywania parametrów przez query string. Musimy stworzyć metodę na którą będzie mapowany url. Następnie podajemy jako listę parametrów metody wszystkie zmienne których się spodziewamy. Każdy parametr adnotujemy @RequestParam i nadajemy mu nazwę taką jak klucz który będziemy przekazywać podczas uruchomienia aplikacji:

@RequestMapping("/querystring")
@ResponseBody
public String queryStringMapping(
@RequestParam String param1,
@RequestParam String param2) {
return String.format("Otrzymane wartości: param1=%s, param2=%s", param1, param2);
}

I to w zasadzie wystarczy. Po uruchomieniu aplikacji i przejściu pod adres http://localhost:8080/querystring?param1=asd&param2=asd zostanie nam wyświetlony tekst:

Otrzymane wartości: param1=asd, param2=asd

Parametry opcjonalne

Spróbujmy wejść teraz na tą samą stronę nie podając jednego z parametrów, korzystając z takiego url: http://localhost:8080/querystring?param1=asd. Otrzymamy błąd 400 z informacją, że brakuje zdefiniowanego argumentu param2.

Czasem chcemy aby część parametrów była opcjonalna. Aby tak się stało należy dodać do adnotacji @RequestParam argument required=false.

@RequestMapping("/querystring")
@ResponseBody
public String queryStringMapping(
@RequestParam String param1,
@RequestParam(required = false) String param2) {
return String.format("Otrzymane wartości: param1=%s, param2=%s", param1, param2);
}

Po odświeżeniu strony zwrócony zostanie tekst:

Otrzymane wartości: param1=asd, param2=null

Czyli zamiast param2 otrzymaliśmy null.

Inne nazwy parametrów metody i kluczy w URL

Czasem potrzebujemy nazwać parametr w metodzie inaczej niż klucz przekazany w URL. Przykładowo klucz zawiera pauzy (-) które nie mogą być częścią nazwy parametru. Możemy wtedy przekazać nazwę parametru który ma zostać zmapowany przez atrybut value lub name adnotacji.  Załóżmy, że chcemy aby w kodzie nasze parametry nazywały się p1 i p2, możemy to zrobić w następujący sposób:

@RequestMapping("/querystring")
@ResponseBody
public String queryStringMapping(
@RequestParam("param1") String p1,
@RequestParam(required = false, name = "param2") String p2) {
return String.format("Otrzymane wartości: param1=%s, param2=%s", p1, p2);
}

Automatyczne typowanie zmiennych

Gdy chcemy przkazać w parametrze liczbę, nie musimy jej ręcznie parsować. Wystarczy jako parametr ustawić typ liczbowy i Spring dokona konwersji za nas. W przypadku gdy spodziewamy się wartości liczbowej, a otrzymamy tekst, zostanwe wyrzucony wyjątek.

@RequestMapping("/querystring")
@ResponseBody
public String queryStringMapping(
@RequestParam("param1") String p1,
@RequestParam(required = false, name = "param2") String p2,
@RequestParam int p3) {
return String.format("Otrzymane wartości: param1=%s, param2=%s, p3=%d", p1, p2, p3);
}

Po wpisaniu w przeglądarkę adresu: http://localhost:8080/querystring?param1=asd&p3=123 zostanie nam wyświetlone:

Otrzymane wartości: param1=asd, param2=null, p3=123

Spróbujmy teraz zminieć p3 na jakąś wartość tekstową, np. http://localhost:8080/querystring?param1=asd&p3=txt, wtedy otrzymamy taki wyjątek:

Przekazywanie parametrów przez URL

Jeśli chcemy przekazać parametry w URL musimy zawrzeć tą informację w adnotacji @RequestMapping wstawiając odpowiednie placeholdery w miejsca gdzie będą zmienne. Wartości parametrów trafią jak poprzednio do metody poprzez argumenty, z tą różnicą, że tym razem należy wykorzystać adnotację @PathVariable.

@RequestMapping("/path/{id}")
@ResponseBody
public String pathVariable(@PathVariable String id) {
return String.format("Wartość zmiennej id = %s", id);
}

Przejście na stronę http://localhost:8080/path/identyfikator zwróci nam tekst: Wartość zmiennej id = identyfikator.

Automatyczne typowanie zmiennych

W tym przypadku również możemy zmienić typ parametrów jak to miało miejsce w przypadku query string.

@RequestMapping("/path/{id}")
@ResponseBody
public String pathVariable(@PathVariable int id) {
return String.format("Wartość zmiennej id = %s", id);
}

Również w tym przypadku otrzymamy błąd jeśli spodziewamy się liczby a przekażemy np. tekst.

Parametry opcjonalne

Adnotacja PathVariable również posiada argument required. Jednak w tym przypadku jest to trochę bardziej skomplikowane. Tutaj zmienna jest częścią adresu url, więc jeśli ją po prostu pominiemy to adres nie zostanie rozpoznany i storna nie zostanie wyświetlona. Zamiast niej otrzymamy błąd 404. Jednakże, RequestMapping może przyjąć wiele mapowań URL, więc możemy przkeazać takie w którym nasza zmienna nie występuje i wtedy ją oznaczyć jako required = false.

@RequestMapping({"/path/{id}", "/path"})
@ResponseBody
public String pathVariable(
@PathVariable(required = false) Integer id) {
return String.format("Wartość zmiennej id = %s", id);
}

Warto również zwrócić uwagę, że zmieniłem typ argumentu id z int na Integer. Zabieg ten jest konieczny ponieważ int nie może przyjąć wartości null, jeśli zostawimy malego inta i nie podamy wartości parametru dostaniemy wtedy błąd.

Walidacja otrzymanych danych

Używając zmiennych w URL możemy również przekazać wyrażenie regularne które będzie sprawdzać poprawność danych.

@RequestMapping({"/path/{id:[0-9]{2,5}}", "/path"})
@ResponseBody
public String pathVariable(
@PathVariable(required = false) Integer id) {
return String.format("Wartość zmiennej id = %s", id);
}

Trzeba jednak pamietać, że wyrażenie to jest używane do dopasowania ścieżki, więc jeśli przekażemy parametr który nie pasuje do wyrażenia to otrzymamy błąd 404. W tym przypadku oznacza to, że nie znaleziono mapowania dla danego adresu URL.

Podsumowanie

Spring zapewnia nam bardzo łatwe przekazywanie parametrów do metody. Dzięki temu możemy łatwo i szybko tworzyć dynamiczne strony, oszczędza to czas który byśmy musieli w innym przypadku spędzić na kodowaniu. Dodatkowo otrzymujemy podstawowe narzędzia do sprawdzenia poprawności przekazywanych parametrów.

Trzeba również pamiętać, że długość URL jest ograniczona. Wielkość tego ograniczenia jest definiowana w konfiguracji serwera. Specyfikacja HTTP mówi, że nie powinno być to mniej niż 8000 oktetów (oktet to 8 bitów).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

%d