Skip to content

函数式端点 (Functional Endpoints)

Spring Web MVC 包含 WebMvc.fn,这是一个轻量级的函数式编程模型。在该模型中,函数被用来路由和处理请求,且契约设计为不可变的。它是基于注解编程模型的替代方案,但同样运行在 DispatcherServlet 之上。

概览 (Overview)

在 WebMvc.fn 中,HTTP 请求由 HandlerFunction 处理:该函数接收 ServerRequest 并返回 ServerResponse。 路由则由 RouterFunction 完成:该函数接收 ServerRequest 并返回一个可选的 HandlerFunction

快速示例

java
// 定义路由
RouterFunction<ServerResponse> route = route()
    .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
    .GET("/person", accept(APPLICATION_JSON), handler::listPeople)
    .POST("/person", handler::createPerson)
    .build();

// 定义处理器
public class PersonHandler {
    public ServerResponse getPerson(ServerRequest request) {
        String id = request.pathVariable("id");
        Person person = repository.find(id);
        return ok().body(person);
    }
}
kotlin
// 使用 Kotlin DSL 定义路由
val route = router {
    accept(APPLICATION_JSON).nest {
        GET("/person/{id}", handler::getPerson)
        GET("/person", handler::listPeople)
    }
    POST("/person", handler::createPerson)
}

核心接口

1. ServerRequest

可以通过 body() 方法读取请求体,通过 pathVariable() 获取路径变量,或者通过 bind() 方法将参数绑定到对象。

2. ServerResponse

不可变接口,提供流式 Builder 来构建响应,例如设置状态码、Headers 或 Body。支持异步结果(如 CompletableFuturePublisher)作为 Body。

3. RouterFunction

用于路由。通常使用 RouterFunctions.route() 提供的 Fluent Builder 或 Kotlin DSL 来创建。支持嵌套路由(Nested Routes),可以提取公共的路径前缀或 Predicate 条件。

过滤器 (Filtering)

你可以通过 beforeafterfilter 方法为路由添加逻辑(类似于注解模型中的拦截器或过滤器)。


补充教学

1. 为什么选择函数式模型?

  • 无副作用:所有的请求和响应都是不可变的,便于测试和并发处理。
  • 显式而非隐式:在注解模型中,请求是如何映射到方法的由 Spring 内部黑盒处理;在函数式模型中,你可以清晰地看到路由匹配的顺序(路由是按定义顺序计算的)。
  • 启动速度:相比于扫描成百上千个注解,直接执行 lambda 函数的启动开销更小。

2. 精位理解:路由匹配顺序

注意:函数式路由是按顺序匹配的。 如果你定义了:

  1. GET("/{id}", ...)
  2. GET("/all", ...) 请求 /all 永远会被第一个路由捕获(因为 "all" 被当作了 id)。在注解模型中,Spring 会自动选择“最精确”的匹配,但在 WebMvc.fn 中,你必须手动将具体的路由放在通用的路由之前。

3. 代码组织建议

不要在 RouterFunction 内部写过长的 Lambda 逻辑。推荐遵循以下模式:

  • Handler 类:负责业务逻辑处理,输入 ServerRequest,输出 ServerResponse
  • Routes 类:只负责将 URL 路径映射到 Handler 的方法引用上。
  • Configuration 类:将 RouterFunction 注册为 Spring Bean。

Based on Spring Framework.