日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【Spring 5】响应式Web框架实战(下)

發(fā)布時(shí)間:2024/1/17 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Spring 5】响应式Web框架实战(下) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

-?【Spring 5】響應(yīng)式Web框架前瞻?
-?響應(yīng)式編程總覽?
-?【Spring 5】響應(yīng)式Web框架實(shí)戰(zhàn)(上)

1 回顧

上篇介紹了如何使用Spring MVC注解實(shí)現(xiàn)一個(gè)響應(yīng)式Web應(yīng)用(以下簡(jiǎn)稱RP應(yīng)用),本篇接著介紹另一種實(shí)現(xiàn)方式——Router Functions。

2 實(shí)戰(zhàn)

2.1 Router Functions

Router Functions是Spring 5新引入的一套R(shí)eactive風(fēng)格(基于Flux和Mono)的函數(shù)式接口,主要包括RouterFunction,HandlerFunction和HandlerFilterFunction,分別對(duì)應(yīng)Spring MVC中的@RequestMapping,@Controller和HandlerInterceptor(或者Servlet規(guī)范中的Filter)。

和Router Functions搭配使用的是兩個(gè)新的請(qǐng)求/響應(yīng)模型,ServerRequest和ServerResponse,這兩個(gè)模型同樣提供了Reactive風(fēng)格的接口。

2.2 示例代碼

下面接著看我GitHub上的示例工程里的例子。

2.2.1 自定義RouterFunction和HandlerFilterFunction

@Configuration public class RestaurantServer implements CommandLineRunner {@Autowiredprivate RestaurantHandler restaurantHandler;/*** 注冊(cè)自定義RouterFunction*/@Beanpublic RouterFunction<ServerResponse> restaurantRouter() {RouterFunction<ServerResponse> router = route(GET("/reactive/restaurants").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::findAll).andRoute(GET("/reactive/delay/restaurants").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::findAllDelay).andRoute(GET("/reactive/restaurants/{id}").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::get).andRoute(POST("/reactive/restaurants").and(accept(APPLICATION_JSON_UTF8)).and(contentType(APPLICATION_JSON_UTF8)), restaurantHandler::create).andRoute(DELETE("/reactive/restaurants/{id}").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::delete)// 注冊(cè)自定義HandlerFilterFunction.filter((request, next) -> {if (HttpMethod.PUT.equals(request.method())) {return ServerResponse.status(HttpStatus.BAD_REQUEST).build();}return next.handle(request);});return router;}@Overridepublic void run(String... args) throws Exception {RouterFunction<ServerResponse> router = restaurantRouter();// 轉(zhuǎn)化為通用的Reactive HttpHandlerHttpHandler httpHandler = toHttpHandler(router);// 適配成Netty Server所需的HandlerReactorHttpHandlerAdapter httpAdapter = new ReactorHttpHandlerAdapter(httpHandler);// 創(chuàng)建Netty ServerHttpServer server = HttpServer.create("localhost", 9090);// 注冊(cè)Handler并啟動(dòng)Netty Serverserver.newHandler(httpAdapter).block();} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

可以看到,使用Router Functions實(shí)現(xiàn)RP應(yīng)用時(shí),你需要自己創(chuàng)建和管理容器,也就是說Spring 5并沒有針對(duì)Router Functions提供IoC支持,這是Router Functions和Spring MVC相比最大的不同。除此之外,你需要通過RouterFunction的API(而不是注解)來配置路由表和過濾器。對(duì)于簡(jiǎn)單的應(yīng)用,這樣做問題不大,但對(duì)于上規(guī)模的應(yīng)用,就會(huì)導(dǎo)致兩個(gè)問題:1)Router的定義越來越龐大;2)由于URI和Handler分開定義,路由表的維護(hù)成本越來越高。那為什么Spring 5會(huì)選擇這種方式定義Router呢?接著往下看。

2.2.2 自定義HandlerFunction

@Component public class RestaurantHandler {/*** 擴(kuò)展ReactiveCrudRepository接口,提供基本的CRUD操作*/private final RestaurantRepository restaurantRepository;/*** spring-boot-starter-data-mongodb-reactive提供的通用模板*/private final ReactiveMongoTemplate reactiveMongoTemplate;public RestaurantHandler(RestaurantRepository restaurantRepository, ReactiveMongoTemplate reactiveMongoTemplate) {this.restaurantRepository = restaurantRepository;this.reactiveMongoTemplate = reactiveMongoTemplate;}public Mono<ServerResponse> findAll(ServerRequest request) {Flux<Restaurant> result = restaurantRepository.findAll();return ok().contentType(APPLICATION_JSON_UTF8).body(result, Restaurant.class);}public Mono<ServerResponse> findAllDelay(ServerRequest request) {Flux<Restaurant> result = restaurantRepository.findAll().delayElements(Duration.ofSeconds(1));return ok().contentType(APPLICATION_JSON_UTF8).body(result, Restaurant.class);}public Mono<ServerResponse> get(ServerRequest request) {String id = request.pathVariable("id");Mono<Restaurant> result = restaurantRepository.findById(id);return ok().contentType(APPLICATION_JSON_UTF8).body(result, Restaurant.class);}public Mono<ServerResponse> create(ServerRequest request) {Flux<Restaurant> restaurants = request.bodyToFlux(Restaurant.class);Flux<Restaurant> result = restaurants.buffer(10000).flatMap(rs -> reactiveMongoTemplate.insert(rs, Restaurant.class));return ok().contentType(APPLICATION_JSON_UTF8).body(result, Restaurant.class);}public Mono<ServerResponse> delete(ServerRequest request) {String id = request.pathVariable("id");Mono<Void> result = restaurantRepository.deleteById(id);return ok().contentType(APPLICATION_JSON_UTF8).build(result);} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

對(duì)比上篇的RestaurantController,由于去除了路由信息,RestaurantHandler變得非常函數(shù)化,可以說就是一組相關(guān)的HandlerFunction的集合,同時(shí)各個(gè)方法的可復(fù)用性也大為提升。這就回答了上一小節(jié)提出的疑問,即以犧牲可維護(hù)性為代價(jià),換取更好的函數(shù)特性。

2.3 單元測(cè)試

@RunWith(SpringRunner.class) @SpringBootTest public class RestaurantHandlerTests extends BaseUnitTests {@Autowiredprivate RouterFunction<ServerResponse> restaurantRouter;@Overrideprotected WebTestClient prepareClient() {WebTestClient webClient = WebTestClient.bindToRouterFunction(restaurantRouter).configureClient().baseUrl("http://localhost:9090").responseTimeout(Duration.ofMinutes(1)).build();return webClient;} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

和針對(duì)Controller的單元測(cè)試相比,編寫Handler的單元測(cè)試的主要區(qū)別在于初始化WebTestClient方式的不同,測(cè)試方法的主體可以完全復(fù)用。

3 小結(jié)

到此,有關(guān)響應(yīng)式編程的介紹就暫且告一段落。回顧這四篇文章,我先是從響應(yīng)式宣言說起,然后介紹了響應(yīng)式編程的基本概念和關(guān)鍵特性,并且詳解了Spring 5中和響應(yīng)式編程相關(guān)的新特性,最后以一個(gè)示例應(yīng)用結(jié)尾。希望讀完這些文章,對(duì)你理解響應(yīng)式編程能有所幫助。歡迎你到我的留言板分享,和大家一起過過招。

4 參考

  • Spring Framework Reference - WebFlux framework
  • spring-framework Reactive Tests
  • poutsma/web-function-sample

總結(jié)

以上是生活随笔為你收集整理的【Spring 5】响应式Web框架实战(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。