响应式编程WebFlux基础API

WebFlux的工作流程

在WebFlux中,主要的组件包括:

  • Reactor: Reactor是WebFlux底层使用的响应式编程库,提供了MonoFlux这两种响应式类型,分别用于表示0-1个和0-N个异步序列元素。
  • WebHandler: 是处理请求的核心接口,所有的请求都会被分配给一个WebHandler来处理。
  • HandlerMapping: 用于将请求映射到对应的WebHandler
  • HandlerAdapter: 用于适配WebHandler的执行,使其能够处理请求并返回响应。
  • WebFilter: 类似于Servlet中的Filter,可以在请求处理前后进行拦截和处理。
  • ServerResponseServerRequest: 分别代表HTTP的响应和请求,在WebFlux中用于处理非阻塞的请求和响应。
  • RouterFunction: 用于声明式地定义路由规则,将请求映射到处理器函数。

工作流程图

Request Dispatch Map to Filter Process Response Return Use Async Processing Client Server HandlerMapping WebHandler WebFilter HandlerAdapter ServerResponse Reactor

在这个流程中:

  1. 客户端发送请求到服务器。
  2. 服务器接收到请求,并将其分发给HandlerMapping
  3. HandlerMapping根据请求信息将其映射到对应的WebHandler
  4. WebFilter可以在请求到达WebHandler之前或之后进行拦截和处理。
  5. WebHandler处理请求,可能会使用Reactor库中的MonoFlux进行异步处理。
  6. HandlerAdapterWebHandler的处理结果适配成服务器可以发送的响应。
  7. 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支持等信息。

java 复制代码
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 接口,因此 DispatcherHandlerWebHandler 的一种具体实现。 WebHandler 接口定义了处理 HTTP 请求的方法,而 DispatcherHandler 实现了这个接口,提供了处理请求的具体实现。

WebHandler 接口的主要方法是 handle,用于处理 HTTP 请求。DispatcherHandler 通过实现这个接口,提供了对请求的分发和处理的支持。下面是 WebHandler 接口的声明:

java 复制代码
public interface WebHandler {
    Mono<Void> handle(ServerWebExchange exchange);
}

DispatcherHandler 通过实现 WebHandler 接口,定义了处理请求的具体逻辑。在 DispatcherHandler 中,handle 方法被实现为请求的分发和处理,如代码所示。

java 复制代码
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    // 如果 handlerMappings 为 null,返回一个包含错误信息的 Mono
    if (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));
}

所以,DispatcherHandlerWebHandler 的一种实现,用于实现对请求的分发和处理。在 Spring WebFlux 中,DispatcherHandler 是整个请求处理流程的核心组件之一。

WebFlux常用API

  1. RouterFunctions:
    RouterFunctions 是用于定义路由的主要接口。通过它,你可以定义请求的映射和处理。

    java 复制代码
    @Configuration
    public class MyRouterConfig {
    
        @Bean
        public RouterFunction<ServerResponse> myRoutes(MyHandler handler) {
            return RouterFunctions.route(GET("/api/resource/{id}"), handler::handleResource)
                    .andRoute(POST("/api/resource"), handler::createResource);
        }
    }
  2. HandlerFunction:
    HandlerFunction 用于处理请求,并返回响应。你需要为每个路由定义一个处理函数。

    java 复制代码
    @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));
        }
    }
  3. ServerRequest 和 ServerResponse:
    ServerRequest 表示一个 HTTP 请求,而 ServerResponse 表示一个 HTTP 响应。在处理函数中,你可以通过这两个对象来获取请求信息和构建响应。

    java 复制代码
        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);
        }
  4. Mono 和 Flux:
    MonoFlux 是 Reactor 框架中的概念,但在 Spring WebFlux 中也经常用到。Mono 用于表示包含零个或一个元素的异步序列,而 Flux 用于表示包含零个或多个元素的异步序列。

    java 复制代码
        public Mono<ServerResponse> createResource(ServerRequest request) {
            // 处理 POST 请求逻辑
            // 返回 Mono<ServerResponse>
            return Mono.just("Hello, WebFlux!")
                    .flatMap(response -> ServerResponse.ok().bodyValue(response));
        }
  5. WebClient:
    WebClient 是 Spring WebFlux 提供的用于进行 HTTP 请求的客户端。它支持异步和响应式编程。

    java 复制代码
        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);
        }
  6. MediaType 和 Content-Type:
    MediaType 类用于表示媒体类型,而 Content-Type 则是 HTTP 请求和响应中用于指定实体主体的媒体类型。

    java 复制代码
    public Mono<ServerResponse> handleResource(ServerRequest request) {
        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue("{ \"message\": \"Hello, WebFlux!\" }");
    }
  7. ExceptionHandler:
    ExceptionHandler 用于全局处理异常,你可以通过实现 WebExceptionHandler 接口来自定义异常处理逻辑。

    java 复制代码
    @Component
    @Order(-2) // 定义处理器的顺序
    public class GlobalExceptionHandler implements WebExceptionHandler {
    
        @Override
        public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
            // 处理其他异常
            exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            return exchange.getResponse().setComplete();
        }
    }

学习打卡day09:响应式编程WebFlux基础API

相关推荐
_oP_i10 分钟前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx13 分钟前
android sqlite 数据库简单封装示例(java)
android·java·数据库
武子康38 分钟前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
豪宇刘2 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意2 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
FF在路上3 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进3 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人3 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.3 小时前
Mybatis-Plus
java·开发语言
不良人天码星3 小时前
lombok插件不生效
java·开发语言·intellij-idea