springboot整合spring5-webflux从0开始的实战及源码解析上篇⽂章<>介绍了spring5.0 新出来的异步⾮阻塞服务,很多读者说太理论了,太单调了,这次我们就通过⼀个从0开始的实例实战⼀下。
1.准备⼯作
spring 提供的IDE⼯STS,配置好maven即可
2.创建spring boot start项⽬spring5-webflux,并添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /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&le</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>spring framework
3.增加处理器HelloWorldHandler
ample.demo;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.active.function.BodyInserters;
import org.active.function.server.ServerRequest;
import org.active.function.server.ServerResponse;
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
ample.demo;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.springframework.http.MediaType;
import org.active.function.server.RequestPredicates;
import org.active.function.server.RouterFunction;
import org.active.function.server.RouterFunctions;
import org.active.function.server.ServerResponse;
@Configuration
public class HelloWorldRouter {
@Bean
public 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<ServerResponse> route =
* ute(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
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> Handler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.
flatMap(result -> handleResult(exchange, result));
}
此时HandlerMapping已经初始化完成
5.1 获取Handler
AbstractHandlerMapping.java
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
return getHandlerInternal(exchange).map(handler -> {
if (logger.isDebugEnabled()) {
logger.LogPrefix() + "Mapped to " + handler);
}
if (CorsUtils.Request())) {
CorsConfiguration configA = CorsConfiguration(exchange);
CorsConfiguration configB = getCorsConfiguration(handler, exchange);
CorsConfiguration config = (configA != null ? configAbine(configB) : configB);
if (!getCorsProcessor().process(config, exchange) ||
CorsUtils.Request())) {
return REQUEST_HANDLED_HANDLER;
}
}
return handler;
});
}
通过RouterFunctions获取HandlerAdapter
5.2 执⾏HandlerAdapter
HelloWorldHandler的类型是HandlerFunctionAdapter类型,触发HandlerFunctionAdapter执⾏handle⽅法
@Override
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler;
ServerRequest request = RequiredAttribute(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来处理结果
@Override
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
ServerResponse response = (ServerResponse) ReturnValue();
Assert.state(response != null, "No ServerResponse");
return response.writeTo(exchange, new ServerResponse.Context() {
@Override
public List<HttpMessageWriter<?>> messageWriters() {
return messageWriters;
}
@Override
public 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表达式,语法更简洁,但可读性变弱。
参考⽂献:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论