函数式Web - SpringBoot3 特性
在 SpringBoot 3 中 ,有一种新型的函数式Web,它可以将原本的控制器中的逻辑 抽离成 处理器 和 控制器。
# 函数式Web - SpringBoot3 特性
*Spring 技术栈*
在 SpringBoot 3 中 ,有一种新型的函数式Web,它可以将原本的控制器中的逻辑 抽离成 处理器 和 控制器。
## 目录
[TOC]
## 前期准备
在这里我们将演示如何在 SpringBoot3 中实现函数式的控制器设定,首先我们需要引入依赖!
### 引入SpringBoot3的依赖
> 请确保是 SpringBoot3 ,因为这个是新特性,旧版本中可能不存在!
```
    <!--  设置 SpringBoot3 做为父项目 所有的 SpringBoot 项目都应该以此为父项目  -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.5</version>
    </parent>
```
接下来我们还需要将 web 依赖引入进来!
```
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
```
### 构建空的控制器
```
package top.lingyuzhao.springTest.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * @author zhao
 */
@Controller
@ResponseBody
public class TestController {
    
}
```
### 构建启动类
```
package top.lingyuzhao.springTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
 * @author zhao
 */
// 使用这个注解标志当前的类是一个 SpringBoot 应用
@SpringBootApplication(scanBasePackages = {
        "top.lingyuzhao.springTest.controller"
})
public class MAIN {
    public static void main(String[] args) {
        // 在这里就是运行 SpringBoot 应用 会返回一个上下文代码
        final ConfigurableApplicationContext run = SpringApplication.run(MAIN.class, args);
        System.out.println(run + ":开始启动!!!");
    }
}
```
## 正式开始!
### 创建一个处理器
这个处理器中包含很多的函数,函数中包含的就是处理逻辑,每个函数都应该是下面的格式,一定是 `ServerRequest -> ServerResponse` 的格式!++
```
    修饰符 ServerResponse 函数名字 (ServerRequest serverRequest) {
        // 使用 ok 函数代表返回状态码为 200
        return ServerResponse.ok()
                // 在这里返回响应体
                .body("这里就是返回的数据,可以是 json 字符串也可以是其它的东西,比如一个 json 类!");
    }
```
```
    修饰符 ServerResponse 函数名字 (ServerRequest serverRequest) {
        // 使用 badRequest 函数代表返回状态码为 400 通常这里就是出现错误才会调用的!
        return ServerResponse.badRequest()
                // 在这里返回响应体
                .body("这里就是返回的数据,可以是 json 字符串也可以是其它的东西,比如一个 json 类!");
    }
```
下面就是正式创建出来的处理器!
```
package top.lingyuzhao.springTest.controller.handler;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
// 标记为 bean 这样可以确保这个被SpringBoot加载到
// 这个类是将请求信息 以及请求信息中的 id 做为 key 追加到 hashMap 中 并基于此进行增删改查
@Component
public class UserHandler {
    public ServerResponse add(ServerRequest serverRequest) {
        // 使用 ok 函数代表返回状态码为 200
        return ServerResponse.ok()
                // 在这里返回响应体
                .body("添加操作成功!!!\n请求参数:" + serverRequest.params());
    }
    public ServerResponse delete(ServerRequest serverRequest) {
        return ServerResponse.ok()
                .body("删除操作成功!!!\n请求参数:" + serverRequest.params());
    }
    public ServerResponse update(ServerRequest serverRequest) {
        return ServerResponse.ok()
                .body("更新操作成功!!!\n请求参数:" + serverRequest.params());
    }
    public ServerResponse get(ServerRequest serverRequest) {
        return ServerResponse.ok()
                .body("查询操作成功!!!\n请求参数:" + serverRequest.params());
    }
}
```
### 在控制器中创建路由
```
package top.lingyuzhao.springTest.controller;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;
import top.lingyuzhao.springTest.controller.handler.UserHandler;
import static org.springframework.web.servlet.function.RequestPredicates.accept;
import static org.springframework.web.servlet.function.RouterFunctions.route;
/**
 * TestController 类主要用于定义 RESTful 风格的路由规则,
 * 通过配置不同的 HTTP 方法和路径映射到 {@link UserHandler} 中的具体处理方法。
 * 这里使用了 Spring WebFlux 的功能性编程模型来构建路由。
 *
 * @author zhao
 */
@Controller
@ResponseBody
public class TestController {
    /**
     * 请求谓词,接受所有类型的媒体类型(MediaType.ALL)。
     * 这意味着对于指定的路由,无论请求的 Accept 头部是什么,都将匹配。
     */
    private static final RequestPredicate ACCEPT_ALL = accept(MediaType.ALL);
    /**
     * 定义 RouterFunction 负责配置路由规则。
     * 此方法作为 Spring Bean 注册到应用上下文中,用于处理与用户相关的 CRUD 操作。
     *
     * @param userHandler 用户处理器,包含用户相关的业务逻辑方法。
     * @return 一个配置了特定路由规则的 RouterFunction 实例。
     */
    @Bean
    public RouterFunction<ServerResponse> routerFunction(UserHandler userHandler) {
        
        // 使用 route() 方法链式调用来定义路由规则:
        // - GET 请求到 "/add" 路径,将调用 userHandler 的 add 方法处理请求。
        // - GET 请求到 "/delete" 路径,将调用 userHandler 的 delete 方法处理请求。
        // - GET 请求到 "/update" 路径,将调用 userHandler 的 update 方法处理请求。
        // - GET 请求到 "/get" 路径,将调用 userHandler 的 get 方法处理请求。
        
        // 所有路由均接受任意媒体类型(由 ACCEPT_ALL 定义)。
        // 最后调用 build() 方法构建完整的 RouterFunction 实例。
        
        return route()
                .GET("/add", ACCEPT_ALL, userHandler::add)
                .GET("/delete", ACCEPT_ALL, userHandler::delete)
                .GET("/update", ACCEPT_ALL, userHandler::update)
                .GET("/get", ACCEPT_ALL, userHandler::get)
                .build();
    }
}
```
### 启动并测试
在这里我们针对四个服务路径都进行了访问和设置,下面就是我们访问之后的结果!

------
***操作记录***
作者:[SpringBoot 助手](https://www.lingyuzhao.top//index.html?search=24 "SpringBoot 助手")
操作时间:2024-06-26 10:05:58 星期三
事件描述备注:保存/发布
 中国 天津 
[](如果不需要此记录可以手动删除,每次保存都会自动的追加记录)