JAVA NA SERWERZE SPRING Waldemar Korłub Platformy Technologiczne KASK ETI Politechnika Gdańska
Java na serwerze 2 https://zeroturnaround.com/rebellabs/most-popular-java-frameworks-tools-and-libraries-2016/ Aplikacje internetowe stanowią jeden z głównych obszarów zastosowań Javy Bogaty rynek frameworków
Spring MVC Action-driven MVC Pierwsze wydanie: 2002 rok Oryginalnie lekka odpowiedź na ciężką ówcześnie platformę J2EE dla aplikacji klasy enterprise Aktualna wersja: 4.x.x Obecnie Spring MVC jest tylko jednym z wielu komponentów platformy Spring, która rozmiarami nie ustępuje Javie EE Kolejne wersje uwzględniają najnowsze trendy w branży i kreują nowe trendy np. popularyzacja wstrzykiwania zależności
Platforma Spring Spring Framework Spring Boot Spring XD Spring Data Spring Cloud Spring Integration Spring Social Web Services Web Flow Spring Security Spring Mobile Session Spring Batch Spring HATEOAS Spring LDAP Spring For Android
Spring Boot 5 Nie jest frameworkiem internetowym per se Aplikacja internetowa oparta o Spring Boot wykorzystuje Spring MVC oraz inne moduły Spring Boot ułatwia konfigurację projektu Konwencje ponad konfigurację Ułatwia budowanie wersji dystrybucyjnej Archiwum JAR zawierające wszystkie zależności oraz osadzony serwer Tomcat (i jego konfigurację) n Może też zawierać init script do użycia w /etc/init.d Prosta dystrybucja pojedynczy plik Proste uruchamianie bez wdrażania na osobny serwer n java -jar app.jar
Spring Initializr 6 http://start.spring.io/ Umożliwia łatwy wybór modułów i wygenerowanie szkieletu projektu Uzyskany projekt wykorzystuje Spring Boot Maven/Gradle do budowania aplikacji
7 REST API
Back-end 8 Przed erą mobilną aplikacja serwerowa typowo generowała dokumenty HTML dla przeglądarki Współcześnie klient w przeglądarce jest jednym z wielu kanałów dostępu do usług na serwerze Aplikacje mobilne smartphony, tablety, smartwatche Smart TV, Smart Car Nowe aplikacje klienckie wymagają programistycznego API nie dokumentów HTML
Back-end i aplikacje klienckie 9 Skoro serwer i tak musi udostępniać API, to klient w przeglądarce również mógłby z niego korzystać To samo API na serwerze dla wszystkich aplikacji klienckich łatwiejsza konstrukcja serwera Aplikacje klienckie w przeglądarce (web front-end) wykorzystują JavaScriptowe frameworki takie jak: Angular (Google) React (Facebook) Ember Backbone.js
API w architekturze REST 10 Serwer udostępnia zasoby aplikacjom klienckim Dane przesyłane w uniwersalnych formatach, np. JSON, XML Zasoby identyfikowane adresami URI Hierarchiczna struktura adresów, przykładowo: /books kolekcja książek /books/17 pojedyncza książka (o id=17) /books/17/authors kolekcja autorów wybranej książki
API w architekturze REST 11 Operacje na zasobach wykonywane przy użyciu żądań HTTP: GET/POST/PUT/DELETE Żądanie Kolekcja elementów, np. /books Pojedynczy element, np. /books/17 GET Pobranie kolekcji Pobranie elementu POST Dodanie elementu do kolekcji Nie stosuje się PUT Nie stosuje się Aktualizacja elementu DELETE Usunięcie całej kolekcji Usunięcie elementu
API w architekturze REST 12 Wyniki sygnalizowane kodami odpowiedzi HTTP, np.: Żądanie Kolekcja elementów, np. /books Pojedynczy element, np. /books/17 GET 200 OK 200 OK 404 Not Found POST 201 Created (+ Location) 403 Forbidden 405 Method not allowed PUT 405 Method not allowed 200 OK 401 Unauthorized DELETE 200 OK 403 Forbidden 200 OK 403 Forbidden 404 Not Found
Narzędzia do pracy z RESTowym API 13 Do pracy z API konieczne są narzędzia do budowania żądań HTTP (GET/POST/PUT/DELETE) Back-end deweloper chce rozwijać i testować API niezależnie od pracy front-end deweloperów Popularne narzędzia: Postman n Aplikacja Chrome (do pobrania z Chrome Web Store) lub n Aplikacja standalone (do pobrania ze strony producenta) SoapUI n Standalone
14 REST API w Springu Spring Boot + Spring MVC
Request-driven MVC 15 odpowiedź HTTP Aplikacja kliencka (np. przeglądarka) generuje treść odpowiedzi, np. HTML, JSON żądanie HTTP Front-controller Model renderuje wybiera kontroler na podstawie routingu (dispatching) wybiera widok, zwraca model Model zwraca wyniki Controller wywołuje View Logika biznesowa
Spring MVC: action-driven MVC 16 Front-controller DispatcherServlet (klasa dostarczana przez framework) Routing @RequestMapping("/books") Kontrolery @Controller/@RestController Modele danych dla widoków słownik Model Szablony widoków Thymeleaf/JSP i wiele innych Logika biznesowa poza kontrolerem @Service
Action-driven MVC w kontekście REST API 17 Front-controller bez zmian Routing bez zmian Kontrolery bez zmian Modele danych dla widoków odpowiedzi API Model w MVC określa, które wyniki logiki biznesowej mają zostać zaprezentowane klientowi Szablony widoków brak Aplikacja nie generuje widoków (dokumentów HTML) Aplikacja zwraca dane w wybranym formacie, np. JSON Logika biznesowa poza kontrolerem bez zmian
Wygenerowanie projektu 18 1. Spring Initializr: http://start.spring.io/ 2. Określenie GroupId oraz ArtifactId 3. Wybór modułów/zależności: Web JPA Derby (baza danych) 4. Generate Project 5. Pobranie archiwum ZIP i rozpakowanie 6. Otwarcie projektu w ulubionym IDE
Punkt wejścia aplikacji 19 @SpringBootApplication public class BookshopApplication { } public static void main(string[] args) { } SpringApplication.run( BookshopApplication.class, args); Umożliwia prosty start aplikacji: $ java -jar app.jar Uruchamia wbudowany serwer Tomcat i wdraża aplikację
@RestController i @RequestMapping 20 Kontrolery API oznaczone adnotacją @RestController Można wskazać prefiks URI dla wszystkich akcji danego kontrolera Adnotacja @RequestMapping na metodach kontrolera do definiowania routingu, np.: @RequestMapping(path = "/books", method = GET) Specjalizowane adnotacje dla poszczególnych żądań protokołu HTTP: @GetMapping @PostMapping @PutMapping @DeleteMapping
@RestController i @RequestMapping 21 @RestController("/shop") public class ShopController { @GetMapping("/orders") public List<Order> listorders() { } @GetMapping("/orders/{id}") public ResponseEntity<Order> getorder( @PathVariable UUID id) { } } @PostMapping("/orders") public ResponseEntity<Void> addorder( @RequestBody Order order) { }
Wiązanie parametrów 22 Automatyczne wiązanie parametrów metody kontrolera z: Parametrami URI (/abc/{param}): @PathVariable Parametrami GET: @RequestParam Ciałem żądania: @RequestBody n Domyślnie mapowanie z formatu JSON Ciało odpowiedzi budowane na podstawie wartości zwracanej przez metodę Domyślnie mapowanie obiektów do formatu JSON
Wiązanie parametrów 23 @GetMapping("/books/{id}/authors") public List<Author> listbookauthors( @PathVariable Integer id, @RequestParam(name = "sort", required = false) String sort) { } List<Author> authors = /* wczytanie z db */; return authors; Konwersja na tablicę w formacie JSON Dla żądania: GET /books/17/authors?sort=asc id = 17 sort = asc
ResponseEntity<T> 24 Umożliwia sterowanie wszystkimi aspektami odpowiedzi HTTP (kod, ciało, nagłówki), np.: @GetMapping("/orders/{id}") public ResponseEntity<Order> getorder( @PathVariable UUID id) { Order order = ordersservice.find(id); } return isnull(order)? ResponseEntity.notFound().build() : ResponseEntity.ok(order);
@Service 25 Logika biznesowa aplikacji powinna znajdować się poza kontrolerem i powinna być niezależna od protokołu HTTP Za przedstawienie wyników logiki biznesowej w kategoriach protokołu HTTP odpowiada kontroler n np. nie znaleziono produktu o podanym id n W warstwie biznesowej: null n W kontrolerze: odpowiedź 404 Serwisy umożliwiają modelowanie logiki biznesowej
Wstrzykiwanie zależności 26 Komponent nie pozyskuje samodzielnie swoich zależności zamiast tego zależności są dostarczane z zewnątrz Przez parametry konstruktora Przez settery Bezpośrednio do pól obiektu Spring oferuje mechanizm wstrzykiwania zależności do serwisów i kontrolerów Oraz innych komponentów (@Component)
Serwis z zależnościami 27 @Service public class OrdersService{ final EntityManager em; final InvoiceService invoiceservice; zależności serwisu public OrdersService(EntityManager em, InvoiceService invoiceservice){ this.em = em; this.invoiceservice = invoiceservice; } } //...logika biznesowa obsługi zamówień...
Kontroler z zależnościami 28 @RestController public class ShopController { OrdersService ordersservice; zależność kontrolera public ShopController(OrdersService ordersservice) { this.ordersservice = ordersservice; } } /*...akcje kontrolera...*/
Dostarczanie zależności 29 Za budowanie zależności i ich dostarczanie odpowiada framework Spring Spring skanuje wszystkie klasy w projekcie w poszukiwaniu adnotacji @Service/@Controller/ @Component itd. Odnalezione komponenty mogą być wstrzykiwane jako zależności do innych komponentów Gdy potrzebna jest nowa instancja zależności Spring buduje ją wstrzykując najpierw jej własne zależności Jeśli występuje kilka konstruktorów, adnotacja @Autowire wskazuje, którego z nich ma użyć Spring
JPA w Springu 30 Klasy encyjne model biznesowy Model biznesowy to nie to samo, co Model w MVC Model w MVC kontrakt z klientem: Jakie dane przedstawić klientowi Jakie dane klient może wysyłać do aplikacji Model biznesowy: na jakich danych aplikacja operuje wewnętrznie (realizuje logikę biznesową)
Model biznesowy i Model w MVC 31 Mogą posiadać część wspólną, np.: Model w MVC Model biznesowy Model w MVC Model biznesowy
JPA w Springu 32 Konfiguracja w pliku application.properties: #Connection string spring.datasource.url=jdbc:derby://localhost:1527/db #Sterownik dla bazy danych i dialekt języka SQL spring.datasource.driver-class-name=org.apache.derby.jdbc.clientdriver40 spring.jpa.database-platform=org.hibernate.dialect.derbytensevendialect #Nazwa użytkownika bazodanowego i hasło spring.datasource.username=db_user spring.datasource.password=db_pass #Generowanie tabel w bazie danych na podstawie modelu encji spring.jpa.hibernate.ddl-auto=update Instancje klasy EntityManager wstrzykiwane jako zależności komponentów
Automatyczne zarządzanie transakcjami 33 Metody oznaczone adnotacją @Transactional wykonywane w ramach transakcji Użycia transakcji wymagają wszystkie operacje modyfikujące stan w bazie danych, np.: @Transactional public void save(book book) { if (/*nowa książka*/) { em.persist(book); } else { em.merge(book); } }
Automatyczne zarządzanie transakcjami 34 Wycofanie transakcji (ang. rollback) następuje w reakcji na wyjątki RuntimeException, np.: Wyjątek biznesowy: public class OutOfStockException extends RuntimeException { } Metoda w klasie biznesowej (@Service): @Transactional public void placeorder(order order) { for (Book bookstub : order.getbooks()) { Book book = em.find(book.class, bookstub.getid()); if (book.getamount() < 1) throw new OutOfStockException(); } else { int newamount = book.getamount() - 1; book.setamount(newamount); } } em.persist(order); wymusza rollback
35 Pytania?