@RestController 和 RouterFunction 的区别以及RouterFunction 使用详解

@RestController 和 RouterFunction 的区别

@RestController和RouterFunction是Spring WebFlux框架中用于构建响应式Web应用程序的两种不同的方式。

  1. @RestController:

    • @RestController是基于注解的方式,用于定义RESTful风格的控制器类。
    • 通过在方法上使用注解(如@GetMapping、@PostMapping等),可以将HTTP请求映射到相应的处理方法上。
    • @RestController适用于传统的基于注解的MVC模式,它提供了简单直观的方式来处理HTTP请求和生成响应。
  2. RouterFunction:

    • RouterFunction是函数式编程的方式,用于定义路由和处理函数之间的映射关系。
    • 它将HTTP请求的路由规则与处理函数进行绑定,使得请求能够被正确地路由到相应的处理函数进行处理。
    • RouterFunction适用于响应式编程模型,它提供了更灵活的方式来定义路由规则,并支持异步非阻塞的处理方式。

使用方法:

  • @RestController的使用方法:

    1. 创建一个带有@RestController注解的控制器类。
    2. 在方法上使用合适的注解(如@GetMapping、@PostMapping等)来定义请求映射。
    3. 在方法体内编写处理逻辑,并返回相应的数据或视图。
  • RouterFunction的使用方法:

    1. 创建一个RouterFunction对象。
    2. 使用路由函数(如route、GET、POST等)定义路由规则和处理函数之间的映射关系。
    3. 在处理函数中编写异步非阻塞的处理逻辑,并返回相应的数据或视图。

@RestController和RouterFunction是两种不同的编程模型,选择使用哪种方式取决于具体的需求和开发风格。

@RestController 和 RouterFunction 的使用

@RestController示例:

@RestController
@RequestMapping("/example")
public class ExampleController {

    @GetMapping
    public String getExample() {}

    @PostMapping
    public String createExample() {}

    @PutMapping("/{id}")
    public String updateExample(@PathVariable String id) {}

    @DeleteMapping("/{id}")
    public String deleteExample(@PathVariable String id) {}
}

RouterFunction示例:

首先准备一个测试方法类

import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;

/**
 * @Author Admin
 * @Date 2023/9/5 21:20
 * @Description ExampleHandler
 **/
@Component
public class ExampleHandler {

    public ServerResponse getExample(ServerRequest request) {
        // 获取参数信息
        String id = request.pathVariable("id");
        // 处理获取示例的逻辑
        return ServerResponse.ok().body("GET-查询请求, 参数信息:["+id+"]: Get example");
    }

    public ServerResponse createExample(ServerRequest request) {
        // 处理创建示例的逻辑
        return ServerResponse.ok().body("POST-创建请求: Create example");
    }

    public ServerResponse updateExample(ServerRequest request) {
        // 获取参数信息
        MultiValueMap<String, String> params = request.params();
        // 处理更新示例的逻辑
        return ServerResponse.ok()
                .body("UPDATE-修改请求, 参数信息:[" + params.toSingleValueMap() + "]: Update example");
    }

    public ServerResponse deleteExample(ServerRequest request) {
        // 接收参数
        String delId = request.pathVariable("delId");
        // 处理删除示例的逻辑
        return ServerResponse.ok().body("Delete-删除请求, 参数信息:[" + delId + "]: Delete example");
    }

    public ServerResponse getInfo(ServerRequest request) {
        // 处理获取示例的逻辑
        return ServerResponse.ok().body("GET-查询请求: Get getInfo");
    }
}

(1)编写方式一:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.function.RequestPredicates;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;

import static org.springframework.web.servlet.function.RequestPredicates.GET;

/**
 * @Author Admin
 * @Description RouterFunction的使用
 **/
@Configuration
public class TestController {

    @Bean
    public RouterFunction<ServerResponse> routeExampleHandler(ExampleHandler exampleHandler) {
        RouterFunctions.Builder route = RouterFunctions.route();
        route = route.GET("/example/{id}", exampleHandler::getExample);
        route = route.POST("/example", exampleHandler::createExample);
        route = route.PUT("/example/update", exampleHandler::updateExample);
        route = route.DELETE("/example/{delId}", exampleHandler::deleteExample);
        return route.build();

    }

}

请求及响应

  • GET请求:

  • POST请求:

  • PUT请求:

  • DELETE请求:

以上是RouterFunction函数请求增删改查的四种请求方式,也可以换成链式写法:

    @Bean
    public RouterFunction<ServerResponse> routeExampleHandler(ExampleHandler exampleHandler) {
        return RouterFunctions.route()
                .GET("/example", exampleHandler::getExample)
                .POST("/example", exampleHandler::createExample)
                .PUT("/example/update", exampleHandler::updateExample)
                .DELETE("/example/{delId}", exampleHandler::deleteExample)
                .build();
    }

路由嵌套,RouterFunctions中nest方法

RouterFunction。它可以将一组相关的路由规则进行分组,并将它们作为一个整体应用到主路由上。RouterFunctions.nest的使用示例如下:

    @Bean
    public RouterFunction<ServerResponse> mainRouterFunction(ExampleHandler exampleHandler) {
        return RouterFunctions.route()
                .path("/api", builder -> builder
                        .nest(RequestPredicates.path("/example"), nestedBuilder -> nestedBuilder
                                .GET("/{id}", exampleHandler::getExample)
                                .POST("", exampleHandler::createExample)
                        )
                        .GET("/info", exampleHandler::getInfo)
                )
                .build();
    }

在上面的示例中,我们定义了一个mainRouterFunction方法,返回类型为RouterFunction<ServerResponse>。在该方法内,我们使用RouterFunctions.route()创建主路由构建器,并使用.path()方法来定义路径匹配规则。

.path("/api", builder -> builder ...)中,我们将一组相关的路由规则分组到/api路径下。然后,在嵌套的.nest(RequestPredicates.path("/example"), nestedBuilder -> nestedBuilder ...)中,我们将另一组路由规则分组到/api/example路径下。

通过使用RouterFunctions.nest,我们可以更好地组织和管理路由规则,使代码结构更清晰,并提高可读性和可维护性。

直接使用RouterFunctions构建一个请求

    @Bean
    public RouterFunction<ServerResponse> mainRouterFunction(ExampleHandler exampleHandler) {
        return RouterFunctions.route(GET("/api/example/{uid}"),
                request -> {
                    Long uid = Long.valueOf(request.pathVariable("uid"));
                    return ServerResponse.ok().body("路径 /api/example 参数信息: " + uid);
                }
        );
    }

API文档 RouterFunction<T extends ServerResponse>

accept(RouterFunctions.Visitor visitor)
接受给定的访问者。

and(RouterFunction<T> other)
返回一个组合路由函数,该函数首先调用该函数,然后在该路由没有结果的情况下调用另一个函数(相同响应类型T)。

andNest(RequestPredicate predicate, RouterFunction<T> routerFunction)
如果路由不匹配且给定的请求谓词适用,则返回一个组成的路由函数,该函数会路由到给定的路由器函数。

andOther(RouterFunction<?> other)
返回一个组成的路由函数,该函数首先调用此函数,如果此路由没有结果,则调用另一个函数(不同响应类型)。

andRoute(RequestPredicate predicate, HandlerFunction<T> handlerFunction)
如果路由不匹配且给定的请求谓词适用,则返回一个组成的路由函数,该函数会路由到给定的处理函数。

filter(HandlerFilterFunction<T,S> filterFunction)
使用给定的过滤函数过滤此函数路由的所有处理函数。

route(ServerRequest request)
返回与给定请求匹配的处理函数。

withAttribute(String name, Object value)
返回一个带有给定属性的新路由函数。

withAttributes(Consumer<Map<String,Object>> attributesConsumer)
返回一个新的路由函数,并使用给定的消费者操作属性。

API文档链接 RouterFunction<T extends ServerResponse>

RouterFunction 实现原理:

1、路由器函数注册:通过 RouterFunctions 类的静态方法创建 RouterFunction 对象,并使用路由器函数将请求映射到处理程序函数上。

2、请求匹配:当收到一个 HTTP 请求时,Spring WebFlux 框架会根据请求的 URL、HTTP 方法等信息进行匹配。

3、处理程序函数执行:一旦找到与请求匹配的路由器函数,框架会调用相应的处理程序函数来处理请求。处理程序函数可以是一个 Lambda 表达式、方法引用或其他函数式编程方式定义的函数。

4、响应生成:处理程序函数执行完成后,会生成一个响应对象,包含要返回给客户端的数据和相关的 HTTP 状态码、头部信息等。

5、响应发送:最后,框架将生成的响应发送给客户端。

猜你喜欢

转载自blog.csdn.net/amosjob/article/details/132700187