Cześć. Wielu z was prawdopodobnie zaczynając tworzyć swoją aplikację webową martwiło się “jak to udokumentować?”, “gdzie przechowywać spis wszystkich endpointów?” lub “jak łatwo wysyłać zapytania do konkretnego endpointa bez użycia aplikacji?”. Znane problemy mają to do siebie, iż ludzie szukają zawsze łatwego i przenośnego rozwiązania. Wyżej wymienione problemy w świecie Javy można łatwo rozwiązać dzięki Swaggera. Dzisiaj dowiesz się jak go dodać do projektu i jak zrobić podstawową konfigurację. W następnym wpisie natomiast pociągniemy temat w bardziej zaawansowanym kierunku (część druga już dostępna tutaj!).
Czym jest ten Swagger ?
Jak już się pewnie możesz domyśleć ze wstępu, Swagger to biblioteka, które pozwala łatwo wizualizować i korzystać z dostępnego w aplikacji API przy okazji tworząc jego dokumentację. Podstawowa konfiguracja Swaggera trwa zwykle kilkanaście minut. o ile nie jesteś pewien w co się pakujesz, możesz zobaczyć przykład stworzony przez autorów biblioteki tutaj.
W tym poście będę bazować na SpringFox, czyli nakładce na Swaggera, która jeszcze bardziej ułatwia dołączenie Swaggera do projektu korzystającego ze Springa.
Projekt bazowy
Podstawowy projekt wygenerujemy sobie ze strony Springa, która ułatwia generowanie podstawowych projektów. Przejdźmy więc tutaj. o ile chodzi o system buildów, standardowo będę bazować na Gradle’u. Z dependencji potrzebna nam będzie tylko część webowa (wpisz “web” w “Search for dependencies”). U mnie wygląda to tak:
Po wygenerowaniu projektu struktura powinna wyglądać nastepująco:
Nic nadzwyczajnego, prawda? Teraz sprawdźmy, czy dobrze projekt się wygenerował. Uruchom program. o ile nie jesteś obeznany ze Springiem lub nie korzystasz z zaawansowanego IDE, sprawę załatwisz wpisując w terminalu będąc w głównym folderze projektu:
./gradlew bootRunPrzejdź na stronę http://localhost:8080. o ile zobaczysz błąd taki jak poniżej to znaczy, iż aplikacja…działa. Poważnie.
Pierwsze zapytania do aplikacji
Automatyczna dokumentacja i zgrabne wyświetlenie API to świetna rzecz. Trudno jednak dokumentować aplikację, o ile nie ma żadnych funkcjonalności. o ile tu jesteś, to zakładam, iż podstawy Springa oraz pojęcie o zapytaniach HTTP masz. Inaczej nie jestem w stanie zagwarantować, iż wszystko będzie dla Ciebie jasne (mimo tego, iż naprawdę się staram).
Aby mieć na czym operować, stworzymy pierwszy RESTowy kontroler. Przejdź do głównego package’u (u mnie to będzie pl.arturczopek) i w nim stwórz klasę HelloController, a w nim prostą metodę hello(), która będzie zwracała wiadomość “Hello, swagger!”. Powinno to wyglądać tak:
Następnie naniesiemy odpowiednie adnotację na nasz kontroller.
- dodaj do klasy adnotację @RestController. Mówi ona, iż nasza klasa jest kontrolerem RESTowym
- dodaj do metody hello() adnotację @RequestMapping(“/hello”). Mówi ona, iż o ile w przeglądarce przejdziemy pod adres /hello, ujrzymy wynik wywołania funkcji hello() w postaci “prostej” lub jako JSON dla bardziej zaawansowanych struktur. Zapewnia nam to dodanie adnotacji @RestController do kontrolera. U nas zwracany jest String, więc ujrzymy prostą wiadomość. Domyślnie dla adnotacji @RequestMapping() zapytania są typu GET.
Po naniesionych adnotacjach kontroler powinien wyglądać tak:
Mamy kontroler, powinien on nam pokazać wiadomość. Uruchom aplikację ponownie i przejdź do http://localhost:8080/hello. o ile wszystko poszło dobrze to powinieneś zobaczyć w przeglądarce prostą wiadomość zdefiniowaną wcześniej, czyli:
Hello, swagger!Dodatkowe endpointy
Rozbudujmy aplikację o dodatkowe endpointy. Poziomem skomplikowania nie będą się one różnić za bardzo od tego wcześniejszego, ale wykorzystamy parę możliwych rodzajów zapytań HTTP, takie jak GET, POST i DELETE. Przykładowe endpointy jakie stworzyłem:
Jak widzisz, dodałem w definicjach endpointów rodzaj zapytań, jakie będą dane endpointy konsumować. Kolejność taka, jak wypisana powyżej. Żeby było ciekawiej, endpoint przyjmujący zapytania GET i POST ma taki sam adres. Zobaczysz jednak dalej (o ile jeszcze nie wiesz jak to zrobić), iż Spring to bez problemu rozróżni. Zapytania POST i DELETE nic nie zwracają. Nie chcemy otrzymywać nic, prócz domyślnego statusu powodzenia czyli kodu HTTP 200.
Ciekawostką może być dla Ciebie ostatni endpoint dla rodzaju zapytania DELETE. Zacznijmy może od adresu:
/bye/{name}Widzimy nazwę name “w wąsach”. Oznacza to, iż możemy tutaj przesyłać jakąś wartość w adresie i odwołać się do niej jak do zmiennej. Definiujemy to w argumentach funkcji:
public void byePerson(@PathVariable String name)Jak widzisz, dodajemy tutaj adnotację @PathVariable, która będzie w adresie szukać wartości pod zmienną określoną w adresie o takiej samej nazwie jak nazwa zmiennej, w tym przypadku name. Można to oczywiście parametryzować, ale dobrą praktyką jest używać tu i tu takich samych nazw. o ile wiesz jak, to po ponownym uruchomieniu możesz wysłać na odpowiednie endpointy zapytania odpowiadającego im typu i sprawdzić w konsoli, czy faktycznie wszystko działa. W tym celu polecam użyć Postmana, o którym w najbliższym czasie pewnie więcej coś wspomnę.
Na tą chwilę mamy tylko 3 endpointy, ale pewnie wiesz, iż większe aplikacje mają ich nieraz 10 lub 100 razy więcej. W pewnym momencie ciężko nad tym zapanować. Jakie mamy adresy, co gdzie możemy wysłać…no robi się ciężko. Teraz jest odpowiedni moment dla Swaggera aby nam pomógł. Doczekałeś się.
Swagger , come on!
Aby skorzystać z jego mocy, Swagger musi w projekcie się znaleźć. Dodamy go do dependencji w pliku build.gradle, a adekwatnie nakładkę, o której wcześniej wspomniałem. W pliku tym w bloku dependencies dodaj dwie linie:
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.8.0' compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.8.0'Aby jednak pobrać te zależności, potrzebujemy dodać odpowiednie repozytorium. Wystarczy w bloku repositories dodać tylko wywołanie funkcji jcenter(). Całościowo plik build.gradle prezentuje się więc następująco:
Swagger dołączony, teraz należy go skonfigurować. Zaczniemy więc od stworzenia klasy SwaggerConfig. W niej będziemy trzymać całą konfigurację. Aby Swagger był dostępny, trzeba klasę oznaczyć adnotacją @EnableSwagger2, która mówi Springowi, by dodał Swaggera. Drugą w tym przypadku potrzebną adnotacją jest @Configuration, która mówi, iż klasa posiada konfigurację. W tym przypadku – tak tak – jest to konfiguracja Swaggera. Zasadniczo mógłbyś dodać te adnotacje do głównej klasy aplikacji, ale z czasem, gdy będzie się Twoja konfiguracja rozrastać, warto mieć odpowiednie konfiguracje od siebie odseparowane.
Po ponownym uruchomieniu aplikacji i przejściu pod adres http://localhost:8080/swagger-ui.html zobaczysz już Swaggera bazującego na podstawowej konfiguracji.
Jak widzisz, już mamy wypisane dwa kontrolery: Basic Error Controller, który jest kontrolerem domyślnie tworzonym przez Springa oraz nasz Hello Controller. Tam faktycznie mamy 3 endpointy typu DELETE, GET, oraz POST. Każdy rodzaj zapytania ma swój kolor. Warto też zauważyć, iż z prawej mamy wypisaną nazwę funkcji, która jest pod danym endpointem. Po kliknięciu w endpoint rozwinie się cała lista co możemy tam wysłać, co może być zwrócone itd. Jest to lista interaktywna. Oznacza to, iż możemy za jej pośrednictwem pod odpowiedni adres wysłać zapytanie. Kliknij na przykład w link /bye/{name}:
Jak widzisz, mamy pokazany wymagany parametr name. Tutaj możemy wpisać wartość tego parametru. Poniżej mamy wypisane kody statusów HTTP i odpowiadające im wiadomości jakie może nam endpoint zwrócić. Spróbuj wpisać jako name swoje imię, a następnie zobacz, co w konsoli aplikacji jest wypisane. Powinieneś zobaczyć komunikat, który Cię żegna
Jeżeli chodzi o wartości podawane jako parametr, może być to czasem cały XML lub JSON, zależy do od endpointu i jego konfiguracji. Wtedy nie wysyłamy de facto parametru, a całe ciało zapytania. Swagger sobie z tym też radzi perfekcyjnie. Zamiast wymaganej wartości możesz zdefiniować endpoint tak, aby jako argument w ciele zapytania przyjmował bardziej złożoną klasę. Zobaczysz w Swaggerze całą jego strukturę. Nie będę tu jednak tego omawiać dzisiaj. Dla ułatwienia dodam tylko, iż wystarczy poszukać, czym jest w Springu adnotacja @RequestBody.
Podsumowanie części 1
Cóż, dzisiaj to by było na tyle. Zobaczyłeś, jak dodać Swaggera do projektu. Konfiguracja była banalna, ale wszystkie parametry na tą chwilę są domyślne. Pokażę Ci jednak w następnej części jak można konfigurację dostosować pod swoje potrzeby, co pozwoli wykorzystać moc tego narzędzia w pełni. Myślę jednak, iż już dostrzegasz benefity i moc jaka drzemie w tej bibliotece. Sam korzystam ze Swaggera, co z resztą wyjdzie w następnym poście. Tam na przykładzie mojej aplikacji zobaczysz bardziej zaawansowaną konfigurację. Póki co, zachęcam pobawić się ze Swaggerem na właśną ręke. Do następnego!
Kod z pierwszej części dostępny na moim GitHubie.
Link do drugiej części raz jeszcze – tutaj.