WebFlux的工作流程
在WebFlux中,主要的组件包括:
Reactor
: Reactor是WebFlux底层使用的响应式编程库,提供了Mono
和Flux
这两种响应式类型,分别用于表示0-1个和0-N个异步序列元素。WebHandler
: 是处理请求的核心接口,所有的请求都会被分配给一个WebHandler
来处理。HandlerMapping
: 用于将请求映射到对应的WebHandler
。HandlerAdapter
: 用于适配WebHandler
的执行,使其能够处理请求并返回响应。WebFilter
: 类似于Servlet中的Filter,可以在请求处理前后进行拦截和处理。ServerResponse
和ServerRequest
: 分别代表HTTP的响应和请求,在WebFlux中用于处理非阻塞的请求和响应。RouterFunction
: 用于声明式地定义路由规则,将请求映射到处理器函数。
工作流程图
在这个流程中:
- 客户端发送请求到服务器。
- 服务器接收到请求,并将其分发给
HandlerMapping
。 HandlerMapping
根据请求信息将其映射到对应的WebHandler
。WebFilter
可以在请求到达WebHandler
之前或之后进行拦截和处理。WebHandler
处理请求,可能会使用Reactor
库中的Mono
或Flux
进行异步处理。HandlerAdapter
将WebHandler
的处理结果适配成服务器可以发送的响应。ServerResponse
将响应返回给客户端。
WebFlux核心API
1. HttpHandler与HttpServer
HttpHandler
HttpHandler
是WebFlux中处理HTTP请求的核心接口之一。它代表一个能够处理HTTP请求并生成响应的组件。HttpHandler
可以被看作是一个函数,接受一个HTTP请求并返回一个表示HTTP响应的Publisher
。典型的HttpHandler
可以是一个Lambda表达式或一个实现了接口的类。可用于 Reactor Netty 的适配器, Undertow、Tomcat、Jetty 和任何 Servlet 容器。
HttpServer
HttpServer
是Reactor Netty提供的一个用于构建HTTP服务器的类。它允许你配置服务器的主机名、端口、SSL支持等信息。
public class SimpleHttpHandlerServerExample {public static void main(String[] args) throws IOException {HttpHandler httpHandler = RouterFunctions.toHttpHandler(RouterFunctions.route().GET("/hello", request -> ServerResponse.ok().bodyValue("Hello, WebFlux!")).build());ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);//启动Netty服务器HttpServer.create().host("localhost").port(8080).handle(adapter) //用指定的处理器处理请求.bindNow(); //现在就绑定System.out.println("服务器启动完成....监听8080,接受请求");System.in.read();System.out.println("服务器停止....");}
}
测试
GET http://localhost:8080/hello 响应:Hello, WebFlux!
2. DispatcherHandler
前中讲到WebFlux的工作流程第5步中
WebHandler
用于处理请求
在 Spring WebFlux 中,DispatcherHandler
实现了 WebHandler
接口,因此 DispatcherHandler
是 WebHandler
的一种具体实现。 WebHandler
接口定义了处理 HTTP 请求的方法,而 DispatcherHandler
实现了这个接口,提供了处理请求的具体实现。
WebHandler
接口的主要方法是 handle
,用于处理 HTTP 请求。DispatcherHandler
通过实现这个接口,提供了对请求的分发和处理的支持。下面是 WebHandler
接口的声明:
public interface WebHandler {Mono<Void> handle(ServerWebExchange exchange);
}
而 DispatcherHandler
通过实现 WebHandler
接口,定义了处理请求的具体逻辑。在 DispatcherHandler
中,handle
方法被实现为请求的分发和处理,如代码所示。
@Override
public Mono<Void> handle(ServerWebExchange exchange) {// 如果 handlerMappings 为 null,返回一个包含错误信息的 Monoif (this.handlerMappings == null) {return createNotFoundError();}// 如果是预检请求(CORS pre-flight request),处理预检请求if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {return handlePreFlight(exchange);}// 从 handlerMappings 中获取处理器函数return Flux.fromIterable(this.handlerMappings)// 依次尝试每个 HandlerMapping,获取处理器函数(是开发者编写的处理器函数,Controller中的接口),也是工作流程中第3步.concatMap(mapping -> mapping.getHandler(exchange)) // 取第一个非空的处理器函数,如果都为空,则返回 createNotFoundError.next()// 如果获取处理器函数失败,也返回 createNotFoundError.switchIfEmpty(createNotFoundError())// 处理可能发生的错误,比如处理器函数执行时的异常.onErrorResume(ex -> handleDispatchError(exchange, ex))// 处理请求,传递 ServerWebExchange 和处理器函数.flatMap(handler -> handleRequestWith(exchange, handler));
}
所以,DispatcherHandler
是 WebHandler
的一种实现,用于实现对请求的分发和处理。在 Spring WebFlux 中,DispatcherHandler
是整个请求处理流程的核心组件之一。
WebFlux常用API
-
RouterFunctions:
RouterFunctions
是用于定义路由的主要接口。通过它,你可以定义请求的映射和处理。@Configuration public class MyRouterConfig {@Beanpublic RouterFunction<ServerResponse> myRoutes(MyHandler handler) {return RouterFunctions.route(GET("/api/resource/{id}"), handler::handleResource).andRoute(POST("/api/resource"), handler::createResource);} }
-
HandlerFunction:
HandlerFunction
用于处理请求,并返回响应。你需要为每个路由定义一个处理函数。@Component public class MyHandler {public Mono<ServerResponse> handleResource(ServerRequest request) {// 处理 GET 请求逻辑// 返回 Mono<ServerResponse>String resourceId = request.pathVariable("id");WebClient webClient = WebClient.create("http://localhost:8080");webClient.get().uri("/api/resource/{id}", 123).retrieve().bodyToMono(String.class).subscribe(response -> System.out.println("Response: " + response));// 处理逻辑return ServerResponse.ok().bodyValue("Resource ID: " + resourceId);}public Mono<ServerResponse> createResource(ServerRequest request) {// 处理 POST 请求逻辑// 返回 Mono<ServerResponse>return Mono.just("Hello, WebFlux!").flatMap(response -> ServerResponse.ok().bodyValue(response));} }
-
ServerRequest 和 ServerResponse:
ServerRequest
表示一个 HTTP 请求,而ServerResponse
表示一个 HTTP 响应。在处理函数中,你可以通过这两个对象来获取请求信息和构建响应。public Mono<ServerResponse> handleResource(ServerRequest request) {// 处理 GET 请求逻辑// 返回 Mono<ServerResponse>String resourceId = request.pathVariable("id");WebClient webClient = WebClient.create("http://localhost:8080");webClient.get().uri("/api/resource/{id}", 123).retrieve().bodyToMono(String.class).subscribe(response -> System.out.println("Response: " + response));// 处理逻辑return ServerResponse.ok().bodyValue("Resource ID: " + resourceId);}
-
Mono 和 Flux:
Mono
和Flux
是 Reactor 框架中的概念,但在 Spring WebFlux 中也经常用到。Mono
用于表示包含零个或一个元素的异步序列,而Flux
用于表示包含零个或多个元素的异步序列。public Mono<ServerResponse> createResource(ServerRequest request) {// 处理 POST 请求逻辑// 返回 Mono<ServerResponse>return Mono.just("Hello, WebFlux!").flatMap(response -> ServerResponse.ok().bodyValue(response));}
-
WebClient:
WebClient
是 Spring WebFlux 提供的用于进行 HTTP 请求的客户端。它支持异步和响应式编程。public Mono<ServerResponse> handleResource(ServerRequest request) {// 处理 GET 请求逻辑// 返回 Mono<ServerResponse>String resourceId = request.pathVariable("id");WebClient webClient = WebClient.create("http://localhost:8080");webClient.get().uri("/api/resource/{id}", 123).retrieve().bodyToMono(String.class).subscribe(response -> System.out.println("Response: " + response));// 处理逻辑return ServerResponse.ok().bodyValue("Resource ID: " + resourceId);}
-
MediaType 和 Content-Type:
MediaType
类用于表示媒体类型,而Content-Type
则是 HTTP 请求和响应中用于指定实体主体的媒体类型。public Mono<ServerResponse> handleResource(ServerRequest request) {return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue("{ \"message\": \"Hello, WebFlux!\" }"); }
-
ExceptionHandler:
ExceptionHandler
用于全局处理异常,你可以通过实现WebExceptionHandler
接口来自定义异常处理逻辑。@Component @Order(-2) // 定义处理器的顺序 public class GlobalExceptionHandler implements WebExceptionHandler {@Overridepublic Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {// 处理其他异常exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);return exchange.getResponse().setComplete();} }
学习打卡day09:响应式编程WebFlux基础API