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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring boot整合spring5-webflux从0开始的实战及源码解析

發布時間:2025/4/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot整合spring5-webflux从0开始的实战及源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上篇文章<你的響應阻塞了沒有?--Spring-WebFlux源碼分析>介紹了spring5.0 新出來的異步非阻塞服務,很多讀者說太理論了,太單調了,這次我們就通過一個從0開始的實例實戰一下。

1.準備工作

? ?spring 提供的IDE工STS,配置好maven即可

2.創建spring boot start項目spring5-webflux,并添加依賴

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>spring5-webflux</artifactId><version>0.0.1-SNAPSHOT</version><name>spring5-webflux</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.增加處理器HelloWorldHandler

package com.example.demo;import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Mono;@Component public class HelloWorldHandler {public Mono<ServerResponse> helloWorld(ServerRequest request) {return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("Hello World!"));} }

4.增加路由器,對應HandlerFunction

package com.example.demo;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse;@Configuration public class HelloWorldRouter {@Beanpublic RouterFunction<ServerResponse> routeHelloWorld(HelloWorldHandler helloWorldHandler) {return RouterFunctions.route(RequestPredicates.GET("/helloWorld").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloWorldHandler::helloWorld);} }

默認啟動時,提供了DefaultRouterFunction的實例

/*** Route to the given handler function if the given request predicate applies.* <p>For instance, the following example routes GET requests for "/user" to the* {@code listUsers} method in {@code userController}:* <pre class="code">* RouterFunction&lt;ServerResponse&gt; route =* RouterFunctions.route(RequestPredicates.GET("/user"), userController::listUsers);* </pre>* @param predicate the predicate to test* @param handlerFunction the handler function to route to if the predicate applies* @param <T> the type of response returned by the handler function* @return a router function that routes to {@code handlerFunction} if* {@code predicate} evaluates to {@code true}* @see RequestPredicates*/public static <T extends ServerResponse> RouterFunction<T> route(RequestPredicate predicate, HandlerFunction<T> handlerFunction) {return new DefaultRouterFunction<>(predicate, handlerFunction);}

5.啟動spring boot項目,調試進入DispatchHandler

@Overridepublic Mono<Void> handle(ServerWebExchange exchange) {if (this.handlerMappings == null) {return createNotFoundError();}return Flux.fromIterable(this.handlerMappings).concatMap(mapping -> mapping.getHandler(exchange)).next().switchIfEmpty(createNotFoundError()).flatMap(handler -> invokeHandler(exchange, handler)).flatMap(result -> handleResult(exchange, result));}

此時HandlerMapping已經初始化完成

? ?5.1 獲取Handler

AbstractHandlerMapping.java?

@Overridepublic Mono<Object> getHandler(ServerWebExchange exchange) {return getHandlerInternal(exchange).map(handler -> {if (logger.isDebugEnabled()) {logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);}if (CorsUtils.isCorsRequest(exchange.getRequest())) {CorsConfiguration configA = this.corsConfigurationSource.getCorsConfiguration(exchange);CorsConfiguration configB = getCorsConfiguration(handler, exchange);CorsConfiguration config = (configA != null ? configA.combine(configB) : configB);if (!getCorsProcessor().process(config, exchange) ||CorsUtils.isPreFlightRequest(exchange.getRequest())) {return REQUEST_HANDLED_HANDLER;}}return handler;});}

通過RouterFunctions獲取HandlerAdapter

?

?5.2 執行HandlerAdapter

?

?HelloWorldHandler的類型是HandlerFunctionAdapter類型,觸發HandlerFunctionAdapter執行handle方法

@Overridepublic Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler;ServerRequest request = exchange.getRequiredAttribute(RouterFunctions.REQUEST_ATTRIBUTE);return handlerFunction.handle(request).map(response -> new HandlerResult(handlerFunction, response, HANDLER_FUNCTION_RETURN_TYPE));}

最后調用HelloWorldHandler的helloWorld方法

@Component public class HelloWorldHandler {public Mono<ServerResponse> helloWorld(ServerRequest request) {return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("Hello World!"));} }

5.3 執行HandleResult

private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {return getResultHandler(result).handleResult(exchange, result).onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult ->getResultHandler(exceptionResult).handleResult(exchange, exceptionResult)));}

因HelloWorldRouter返回結果類型是ServerResponse,故調用ServerResponseResultHandler來處理結果

@Overridepublic Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {ServerResponse response = (ServerResponse) result.getReturnValue();Assert.state(response != null, "No ServerResponse");return response.writeTo(exchange, new ServerResponse.Context() {@Overridepublic List<HttpMessageWriter<?>> messageWriters() {return messageWriters;}@Overridepublic List<ViewResolver> viewResolvers() {return viewResolvers;}});}

6.總結

? ?spring mvc和spring webflux是一對兄弟,他們的處理流程類似,mvc是同步阻塞服務,webflux是異步非阻塞服務,它們直接的關系如下:

? ? ?spring webflux 增加了functional endpoint,RouterFunction(RouterFunctions構建)等同于HanderMapping,?HandlerFunction(HandlerFunctionAdapter繼承自HandlerAdapter來代理)等同于HandlerAdapter

? ? spring webflux 引入了spring boot2,Reactor,lambda表達式,語法更簡潔,但可讀性變弱。

參考文獻:

【1】https://www.journaldev.com/20763/spring-webflux-reactive-programming

轉載于:https://www.cnblogs.com/davidwang456/p/10407557.html

總結

以上是生活随笔為你收集整理的spring boot整合spring5-webflux从0开始的实战及源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。