Bevezetés a funkcionális webes keretrendszerbe 5. tavasszal
1. Bemutatkozás
A Spring WebFlux egy új, funkcionális webkeret, amely reaktív elvek alapján épül fel.
Ebben az oktatóanyagban megtudhatjuk, hogyan kell vele a gyakorlatban dolgozni.
Ezt alapul vesszük a Spring 5 WebFlux meglévő útmutatónkba. Ebben az útmutatóban egy egyszerű, reaktív REST alkalmazást hoztunk létre annotáció-alapú összetevők felhasználásával. Itt inkább a funkcionális keretet fogjuk használni.
2. Maven-függőség
Ugyanezre lesz szükségünk spring-boot-starter-webflux az előző cikkben meghatározott függőség:
org.springframework.boot spring-boot-starter-webflux 2.2.6. KÖZLEMÉNY
3. Funkcionális webes keretrendszer
A funkcionális webes keretrendszer egy új programozási modellt vezet be, ahol függvényeket használunk a kérések továbbításához és kezeléséhez.
Az annotáció-alapú modellel szemben, ahol annotáció-leképezéseket használunk, itt fogjuk használni HandlerFunction és RouterFunctions.
Hasonlóan, mint az annotált vezérlőknél, a funkcionális végpontok megközelítése ugyanarra a reaktív veremre épül.
3.1. HandlerFunction
A HandlerFunction olyan funkciót képvisel, amely válaszokat generál a hozzájuk továbbított kérésekre:
@FunctionalInterface nyilvános felület HandlerFunction {Mono fogantyú (ServerRequest kérés); }
Ez a felület elsősorban a Funkció
Bár egy szabványhoz képest Servlet # szolgáltatás (ServletRequest req, ServletResponse res), HandlerFunction nem választ választ bemeneti paraméterként.
3.2. RouterFunction
RouterFunction alternatívájaként szolgál a @RequestMapping annotáció. Használhatjuk a kérelmek továbbítására a kezelő funkciókhoz:
@FunctionalInterface nyilvános felület RouterFunction {Mono útvonal (ServerRequest kérés); // ...}
Általában importálhatjuk a segítő funkciót RouterFunctions.route () útvonalak létrehozásához a teljes útválasztó funkció írása helyett.
Ez lehetővé teszi számunkra a kérelmek továbbítását a RequestPredicate. Ha az állítmány megegyezik, akkor a második argumentum, a kezelő függvény adódik vissza:
nyilvános statikus RouterFunction útvonal (RequestPredicate predikátum, HandlerFunction handlerFunction)
Mert a útvonal() metódus a RouterFunction, láncolhatjuk erőteljes és összetett útválasztási sémák kiépítésére.
4. Reaktív REST alkalmazás funkcionális web használatával
Előző útmutatónkban létrehoztunk egy egyszerű EmployeeManagement REST alkalmazás használatával @RestController és Webkliens.
Most valósítsuk meg ugyanazt a logikát az útválasztó és a kezelő funkciók használatával.
Első, útvonalakat kell létrehoznunk RouterFunction hogy közzétegyük és elfogyasszuk a reaktív folyamatainkat Munkavállalós.
Az útvonalak tavaszi babként vannak regisztrálva, és bármilyen konfigurációs osztályon belül létrehozhatók.
4.1. Egyetlen forrás
Készítsük el az első útvonalat a RouterFunction amely kislemezt jelentet meg Munkavállaló forrás:
@Bean RouterFunction getEmployeeByIdRoute () {visszatérési útvonal (GET ("/ alkalmazottak / {id}"), req -> ok (). Body (workerRepository (). FindEmployeeById (req.pathVariable ("id")), Employee.class )); }
Az első argumentum egy kérés predikátum. Figyelje meg, hogyan használtunk statikusan importált termékeket RequestPredicates.GET módszer itt. A második paraméter meghatározza a kezelő függvényt, amelyet akkor használunk, ha az állítmány érvényes.
Más szavakkal, a fenti példa átirányítja az összes GET-kérést / alkalmazottak / {id} nak nek EmployeeRepository # findEmployeeById (karakterlánc azonosító) módszer.
4.2. Gyűjtemény erőforrása
Ezután egy gyűjtemény-erőforrás közzétételéhez adjunk hozzá egy másik útvonalat:
@Bean RouterFunction getAllEmployeesRoute () {visszatérési útvonal (GET ("/ alkalmazottak"), req -> ok (). Body (workerRepository (). FindAllEmployees (), Employee.class)); }
4.3. Egyetlen forrás frissítése
Végül adjunk hozzá egy útvonalat a Munkavállaló forrás:
@Bean RouterFunction updateEmployeeRoute () {visszatérési útvonal (POST ("/ alkalmazottak / frissítés"), req -> req.body (toMono (Employee.class)). DoOnNext (workerRepository () :: updateEmployee). Akkor (ok () .épít())); }
5. Útvonalak összeállítása
Össze is állíthatjuk az útvonalakat egyetlen útválasztó funkcióban.
Nézzük meg, hogyan lehet kombinálni a fent létrehozott útvonalakat:
@Bean RouterFunction összetett útvonalak () {visszatérési útvonal (GET ("/ alkalmazottak"), req -> ok (). Body (workerRepository (). FindAllEmployees (), Employee.class)) .and (route (GET ("/ alkalmazottak) / {id} "), req -> ok (). test (workerRepository (). findEmployeeById (req.pathVariable (" id ")), Employee.class))). "), req -> req.body (toMono (Employee.class)) .doOnNext (workerRepository () :: updateEmployee) .majd (ok (). build ()))); }
Itt használtuk RouterFunction.and () hogy összekapcsoljuk az útjainkat.
Végül megvalósítottuk a teljes REST API-t, amelyre szükségünk van EmployeeManagement alkalmazás, routerek és kezelők használatával.
Az alkalmazás futtatásához használhatunk külön útvonalakat, vagy a fentiekben létrehozott egyetlen, összetett utat.
6. Útvonalak tesztelése
Tudjuk használni WebTestClient hogy teszteljük az útjainkat.
Ehhez először össze kell kötnünk az útvonalakat a bindToRouterFunction metódust, majd hozza létre a teszt kliens példányt.
Teszteljük a mi getEmployeeByIdRoute:
@Test public void givenEmployeeId_whenGetEmployeeById_thenCorrectEmployee () {WebTestClient kliens = WebTestClient .bindToRouterFunction (config.getEmployeeByIdRoute ()) .build (); Alkalmazott alkalmazott = új alkalmazott ("1", "1. alkalmazott"); adott (workerRepository.findEmployeeById ("1")). willReturn (Mono.just (alkalmazott)); client.get () .uri ("/ alkalmazottak / 1") .exchange () .expectStatus () .isOk () .expectBody (Employee.class) .isEqualTo (alkalmazott); }
és hasonlóan getAllEmployeesRoute:
@Test public void whenGetAllEmployees_thenCorrectEmployees () {WebTestClient client = WebTestClient .bindToRouterFunction (config.getAllEmployeesRoute ()) .build (); Alkalmazottak listája = Arrays.asList (új alkalmazott ("1", "1. alkalmazott"), új alkalmazott ("2", "2. alkalmazott")); Flux alkalmazottFlux = Flux.fromIterable (alkalmazottak); adott (workerRepository.findAllEmployees ()). willReturn (workerFlux); client.get () .uri ("/ alkalmazottak") .exchange () .expectStatus () .isOk () .expectBodyList (Employee.class) .isEqualTo (alkalmazottak); }
Kipróbálhatjuk a mi updateEmployeeRoute azzal állítva, hogy a mi Munkavállaló a példányt a EmployeeRosory:
@Test public void whenUpdateEmployee_thenEmployeeUpdated () {WebTestClient client = WebTestClient .bindToRouterFunction (config.updateEmployeeRoute ()) .build (); Alkalmazott alkalmazott = új alkalmazott ("1", "1. alkalmazott frissítve"); client.post () .uri ("/ alkalmazottak / frissítés") .body (Mono.just (alkalmazott), Employee.class) .exchange () .expectStatus () .isOk (); ellenőrizze (workerRepository) .updateEmployee (alkalmazott); }
További részletek a WebTestClient kérjük, olvassa el a bemutatónkat a munkáról Web Ügyfél és WebTestClient.
7. Összegzés
Ebben az oktatóanyagban bemutattuk az új funkcionális web keretrendszert 5 tavasszal, és megvizsgáltuk két alapvető felületét RouterFunction és HandlerFunction. Megtanultuk azt is, hogyan lehet különféle útvonalakat létrehozni a kérelem kezeléséhez és a válasz elküldéséhez.
Ezenkívül újrateremtettük EmployeeManagement alkalmazás bevezetése a Spring 5 WebFlux útmutatóhoz a funkcionális végpontok modelljével.
Mint mindig, a teljes forráskód megtalálható a Github oldalon.