javascript
Spring Web-Flux – Cassandra后端的功能样式
在上一篇文章中,我介紹了Spring Web-Flux的基礎知識,它表示Spring框架的Web層中的響應式支持。
我已經展示了使用Spring Data Cassandra并在Spring Web Layers中使用傳統注釋支持的端到端示例, 大致如下:
... import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; ...@RestController @RequestMapping("/hotels") public class HotelController {@GetMapping(path = "/{id}")public Mono<Hotel> get(@PathVariable("id") UUID uuid) {...}@GetMapping(path = "/startingwith/{letter}")public Flux<HotelByLetter> findHotelsWithLetter(@PathVariable("letter") String letter) {...}}除了返回類型外,這看起來像傳統的Spring Web注釋,這些端點不是返回域類型,而是通過在Reactor-Core中實現Mono和Flux的實現返回Publisher類型,而Spring-Web則將內容流回。
在本文中,我將介紹一種不同的公開端點的方法-使用功能樣式而不是注釋樣式。 讓我承認,對于我了解暴露Web終結點的功能樣式的理解,我發現Baeldung的文章和Rossen Stoyanchev的文章非常寶貴。
將注釋映射到路線
讓我從一些基于注釋的端點開始,一個是檢索實體,另一個是保存實體:
@GetMapping(path = "/{id}") public Mono<Hotel> get(@PathVariable("id") UUID uuid) {return this.hotelService.findOne(uuid); }@PostMapping public Mono<ResponseEntity<Hotel>> save(@RequestBody Hotel hotel) {return this.hotelService.save(hotel).map(savedHotel -> new ResponseEntity<>(savedHotel, HttpStatus.CREATED)); }在公開端點的功能風??格中,每個端點都將轉換為RouterFunction ,它們可以組成以創建應用程序的所有端點,如下所示:
package cass.web;import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RouterFunction;import static org.springframework.web.reactive.function.server.RequestPredicates.*; import static org.springframework.web.reactive.function.server.RouterFunctions.*;public interface ApplicationRoutes {static RouterFunction<?> routes(HotelHandler hotelHandler) {return nest(path("/hotels"),nest(accept(MediaType.APPLICATION_JSON),route(GET("/{id}"), hotelHandler::get).andRoute(POST("/"), hotelHandler::save)));} }有一些輔助功能(嵌套,路由,GET,接受等),可以輕松地將所有RouterFunction組合在一起。 找到合適的RouterFunction后,該請求由HandlerFunction處理,該函數在上述示例中由HotelHandler抽象,并且保存和獲取功能如下所示:
import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono;import java.util.UUID;@Service public class HotelHandler {...public Mono<ServerResponse> get(ServerRequest request) {UUID uuid = UUID.fromString(request.pathVariable("id"));Mono<ServerResponse> notFound = ServerResponse.notFound().build();return this.hotelService.findOne(uuid).flatMap(hotel -> ServerResponse.ok().body(Mono.just(hotel), Hotel.class)).switchIfEmpty(notFound);}public Mono<ServerResponse> save(ServerRequest serverRequest) {Mono<Hotel> hotelToBeCreated = serverRequest.bodyToMono(Hotel.class);return hotelToBeCreated.flatMap(hotel ->ServerResponse.status(HttpStatus.CREATED).body(hotelService.save(hotel), Hotel.class));}... }這是原始基于注釋的項目支持的所有API的完整RouterFunction的樣子:
import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RouterFunction;import static org.springframework.web.reactive.function.server.RequestPredicates.*; import static org.springframework.web.reactive.function.server.RouterFunctions.*;public interface ApplicationRoutes {static RouterFunction<?> routes(HotelHandler hotelHandler) {return nest(path("/hotels"),nest(accept(MediaType.APPLICATION_JSON),route(GET("/{id}"), hotelHandler::get).andRoute(POST("/"), hotelHandler::save).andRoute(PUT("/"), hotelHandler::update).andRoute(DELETE("/{id}"), hotelHandler::delete).andRoute(GET("/startingwith/{letter}"), hotelHandler::findHotelsWithLetter).andRoute(GET("/fromstate/{state}"), hotelHandler::findHotelsInState)));} }測試功能路線
測試這些路由也很容易,Spring Webflux提供了一個WebTestClient來測試路由,同時提供模擬其背后的實現的能力。
例如,為了測試通過ID的get端點,我將WebTestClient綁定到之前定義的RouterFunction,并使用它提供的斷言來測試行為。
import org.junit.Before; import org.junit.Test; import org.springframework.test.web.reactive.server.WebTestClient; import reactor.core.publisher.Mono;import java.util.UUID;import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when;public class GetRouteTests {private WebTestClient client;private HotelService hotelService;private UUID sampleUUID = UUID.fromString("fd28ec06-6de5-4f68-9353-59793a5bdec2");@Beforepublic void setUp() {this.hotelService = mock(HotelService.class);when(hotelService.findOne(sampleUUID)).thenReturn(Mono.just(new Hotel(sampleUUID, "test")));HotelHandler hotelHandler = new HotelHandler(hotelService);this.client = WebTestClient.bindToRouterFunction(ApplicationRoutes.routes(hotelHandler)).build();}@Testpublic void testHotelGet() throws Exception {this.client.get().uri("/hotels/" + sampleUUID).exchange().expectStatus().isOk().expectBody(Hotel.class).isEqualTo(new Hotel(sampleUUID, "test"));} }結論
定義路由的功能方式絕對不同于基于注釋的方式–我喜歡這是定義端點以及如何處理端點調用的更為明確的方式,注釋總是給人更多的感覺。神奇。
我在github存儲庫中有完整的工作代碼,它可能比本文中的代碼更容易遵循。
翻譯自: https://www.javacodegeeks.com/2017/04/spring-web-flux-functional-style-cassandra-backend.html
總結
以上是生活随笔為你收集整理的Spring Web-Flux – Cassandra后端的功能样式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea 编写javafx_用JavaF
- 下一篇: 邮件域名备案怎么弄(邮件域名备案)