在 WebMvc.fn 中,HTTP 请求是通过 HandlerFunction 处理的:一个接收 ServerRequest 并返回 ServerResponse 的函数。请求和响应对象都有不可变的契约,提供 JDK 8 对 HTTP 请求和响应的友好访问。HandlerFunction 相当于基于注解的编程模型中的 @RequestMapping方法的主体。

传入的请求被路由到具有 RouterFunction 的处理函数:该函数接收 ServerRequest 并返回一个可选的 HandlerFunction(即可选的<HandlerFunction>)。当路由器函数匹配时,将返回一个处理函数;否则将返回一个空的 Optional。RouterFunction 相当于 @RequestMapping注解,但主要区别在于,路由器函数不仅提供数据,还提供行为。

RouterFunctions.route()提供了一个路由器生成器,方便了路由器的创建,如下例所示:

  1. import static org.springframework.http.MediaType.APPLICATION_JSON;
  2. import static org.springframework.web.servlet.function.RequestPredicates.*;
  3. import static org.springframework.web.servlet.function.RouterFunctions.route;
  4. PersonRepository repository = ...
  5. PersonHandler handler = new PersonHandler(repository);
  6. RouterFunction<ServerResponse> route = route()
  7. .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
  8. .GET("/person", accept(APPLICATION_JSON), handler::listPeople)
  9. .POST("/person", handler::createPerson)
  10. .build();
  11. public class PersonHandler {
  12. // ...
  13. public ServerResponse listPeople(ServerRequest request) {
  14. // ...
  15. }
  16. public ServerResponse createPerson(ServerRequest request) {
  17. // ...
  18. }
  19. public ServerResponse getPerson(ServerRequest request) {
  20. // ...
  21. }
  22. }

如果你把 RouterFunction 注册为 Bean,例如通过在 @Configuration类中公开它,它将被 servlet 自动检测到,正如在运行服务器中解释的那样。

例子

该例子使用了后面章节的知识点

  1. package cn.mrcode.study.springdocsread.fn;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.function.RouterFunction;
  5. import org.springframework.web.servlet.function.ServerResponse;
  6. import static org.springframework.http.MediaType.APPLICATION_JSON;
  7. import static org.springframework.web.servlet.function.RequestPredicates.accept;
  8. import static org.springframework.web.servlet.function.RouterFunctions.route;
  9. /**
  10. * @author mrcode
  11. */
  12. @Configuration
  13. public class FnConfig {
  14. @Bean // 交给 ioc 容器
  15. public RouterFunction<ServerResponse> fun1() {
  16. final TestHandler handler = new TestHandler();
  17. RouterFunction<ServerResponse> route = route()
  18. .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
  19. .GET("/person", accept(APPLICATION_JSON), handler::listPeople)
  20. .POST("/person", handler::createPerson)
  21. .build();
  22. return route;
  23. }
  24. }
  1. package cn.mrcode.study.springdocsread.fn;
  2. import org.springframework.web.servlet.function.ServerRequest;
  3. import org.springframework.web.servlet.function.ServerResponse;
  4. /**
  5. * @author mrcode
  6. */
  7. public class TestHandler {
  8. // ...
  9. public ServerResponse getPerson(ServerRequest request) {
  10. final String id = request.pathVariable("id");
  11. return ServerResponse.ok().body("你发送的 ID = " + id);
  12. }
  13. public ServerResponse listPeople(ServerRequest request) {
  14. return ServerResponse.ok().body("Hello World");
  15. }
  16. public ServerResponse createPerson(ServerRequest request) {
  17. return ServerResponse.ok().body("POST");
  18. }
  19. }

启动后,访问 [http://localhost:8080/person/123](http://localhost:8080/person/123) 或则其他两个 URL ,就能访问到上面 testHandler 对应的方法