> For the complete documentation index, see [llms.txt](https://ldbmcs.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ldbmcs.gitbook.io/java/java-frameworks-87/spring/spring-webflux/dispatcherhandler-de-gong-zuo-yuan-li-han-shu-shi-duan-dian.md).

# DispatcherHandler的工作原理（函数式端点）

上一篇咱用传统的 WebMvc 编程风格测试了一个请求，下面咱用后面写的函数式端点编程开发的Handler，看看它的处理有什么相同和不同。

## 1. DispatcherHandler#handle

对，你没看错，它还是来到 `DispatcherHandler` 的 `handle` 方法，证明两种方式最终都是走一个前端控制器。

```java
public 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));
}
```

那套路就跟上一篇的一样了，咱一一来看：

## 2. 选定HandlerMapping

`concatMap(mapping -> mapping.getHandler(exchange))` 的步骤是筛选 HandlerMapping 的，来到 `AbstractHandlerMapping#getHandler` ：

```java
public Mono<Object> getHandler(ServerWebExchange exchange) {
    return getHandlerInternal(exchange).map(handler -> {
        // ......
    });
}
```

进入Lambda表达式中发现 `Handler` 的类型是我自己写的 `RouterConfiguration` 中的Lambda表达式！而且它也帮我映射到了实际处理的 `DemoHandler` ！

![img](https://cdn.nlark.com/yuque/0/2023/png/229542/1673186492202-e571506a-19dc-424a-a55e-b198d9510481.png)

注意这个地方实际上的 `HandlerMapping` 是 `RouterFunctionMapping` ，这个组件咱之前在第31篇留了个缺口，这里咱回顾一下：

### 2.0 RouterFunctionMapping

```java
@Bean
public RouterFunctionMapping routerFunctionMapping() {
    RouterFunctionMapping mapping = createRouterFunctionMapping();
    mapping.setOrder(-1); // go before RequestMappingHandlerMapping
    mapping.setMessageReaders(serverCodecConfigurer().getReaders());
    mapping.setCorsConfigurations(getCorsConfigurations());

    return mapping;
}
```

它有设置一个 `Order` 的属性为 -1，并且后面的单行注释也写得很明白：它会排在 `RequestMappingHandlerMapping` 的前面。这样看来，用**函数式端点开发的映射，优先级会高于用 WebMvc 的注解风格开发的映射**。

对比 `RequestMappingHandlerMapping` ，发现它的 Order 是0，证明 `RouterFunctionMapping` 更靠前：

```java
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
    mapping.setOrder(0);
    // ......
```

另外，`RouterFunctionMapping` 中包含了所有的函数式端点，咱看看它的定义：

```java
public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean {

    @Nullable
    private RouterFunction<?> routerFunction;
```

它里面有一个 `routerFunction` 的属性，它保存了所有的函数式端点。可这样看上去只有一个，说明它肯定有一些组合/合并的动作。

借助IDEA，发现在这个类中有一个 `initRouterFunctions` 方法：

```java
protected void initRouterFunctions() {
    List<RouterFunction<?>> routerFunctions = routerFunctions();
    this.routerFunction = routerFunctions.stream().reduce(RouterFunction::andOther).orElse(null);
    logRouterFunctions(routerFunctions);
}
```

这里它会先获取所有的 `RouterFunction` ，之后在下面有一个将所有 `RouterFunction` 的 `reduce` 操作，它会利用 `RouterFunction` 的 `andOther` 方法，将所有 `RouterFunction` 进行组合。

## 3. 寻找HandlerAdapter

```java
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
    if (this.handlerAdapters != null) {
        for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
            if (handlerAdapter.supports(handler)) {
                return handlerAdapter.handle(exchange, handler);
            }
        }
    }
    return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
```

依旧来到 `invokeHandler` 方法中找 `HandlerAdapter` ，不过这次是函数式端点编程，所以找到的 `HandlerAdapter` 的类型会有所不同：

![img](https://cdn.nlark.com/yuque/0/2023/png/229542/1673186560505-ea990f3d-fbda-4dbc-8969-b175f101f8f1.png)

发现类型为 `HandlerFunctionAdapter` ，不过Debug时想展开看看它里面有什么组成，结果扑了个空。。。（实际上也确实没有对象属性）

## 4. 执行目标方法

```java
public 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));
}
```

注意在 `HandlerFunctionAdapter` 中，所有的 Handler 都可以转换为 `HandlerFunction` 类型。

`RouterFunctions` 类的 `route` 方法会传入 `HandlerFunction` 类型的 lambda表达式：

```java
public static <T extends ServerResponse> RouterFunction<T> route(
    RequestPredicate predicate, HandlerFunction<T> handlerFunction) {
    return new DefaultRouterFunction<>(predicate, handlerFunction);
}
```

下面的return部分的调用，注意第一步：`handlerFunction.handle(request)` ，它会直接拿 `handlerFunction` 调 `handle` 方法，这个操作就相当于实际调用 Controller 的方法，而 HandlerFunction 接口的定义：

```java
@FunctionalInterface
public interface HandlerFunction<T extends ServerResponse> {
    Mono<T> handle(ServerRequest request);
}
```

借助IDEA，发现 `handle` 方法的实现就是我自己写的 `DemoHandler` 里的方法：

![img](https://cdn.nlark.com/yuque/0/2023/png/229542/1673186596390-bf275eb2-c66f-40f2-83d6-70606c7527d2.png)

由此可以发现，原来函数式端点的执行更简单，不需要走反射，直接强转就可以调用 Controller/Handler的目标方法。

## 5. 返回值处理

`DispatcherHandler` 的最后一步，要对上一步的返回值进行处理，会走 `result -> handleResult(exchange, result)` 方法：

```java
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)));
}
```

调用链的第一步获取 `ResultHandler` ，不过这次获取的类型发生了变化：

![img](https://cdn.nlark.com/yuque/0/2023/png/229542/1673186619007-409f83bc-2e56-4d6e-b5ce-75257f17847c.png)

它的类型是 `ServerResponseHandlerResult` ！那咱就有必要看看这个类了，毕竟它跟 `ResponseBodyResultHandler` 肯定是不一样的实现。

### 5.1 ServerResponseHandlerResult

来到 `ServerResponseHandlerResult` 的 `handleResult` 方法：

```java
public 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() {
        @Override
        public List<HttpMessageWriter<?>> messageWriters() {
            return messageWriters;
        }
        @Override
        public List<ViewResolver> viewResolvers() {
            return viewResolvers;
        }
    });
}
```

可以发现它其实也没那么神秘，也是直接拿 `ServerResponse` ，直接调 `writeTo` 方法，向响应流中写入数据。

至此，请求被成功处理。

## 6. 流程图

![img](https://cdn.nlark.com/yuque/0/2023/png/229542/1673186642094-ccf087a9-ef64-4700-b0c4-05c07dd80114.png)

## 7. 小结

1. `RouterFunctionMapping` 用于在函数式端点的映射中寻找对应的目标方法，而且它的优先级高于 `RequestMappingHandlerMapping` 。
2. 函数式端点编程在真正调用目标 Controller/Handler 方法时，相较于传统 WebMvc 方式，不需要走反射，而是直接强转为 `HandlerFunction` 后直接调用目标方法。
