重庆高铁建设网站,深圳seo公司,软件开发培训学校porin,手工迷你饮水机目录 一、WebFlux1.1 定义1.2 WebFlux 与 Spring MVC 区别 二、代码实现2.1 Maven 配置2.2 暴露 RESTful API 接口的方式方式一#xff1a;基于注解的控制器方式二#xff1a;函数式路由器#xff08;Functional Endpoints#xff09; 2.3 测试Service2.4 测试ServiceImpl2… 目录 一、WebFlux1.1 定义1.2 WebFlux 与 Spring MVC 区别 二、代码实现2.1 Maven 配置2.2 暴露 RESTful API 接口的方式方式一基于注解的控制器方式二函数式路由器Functional Endpoints 2.3 测试Service2.4 测试ServiceImpl2.5 测试实体类2.6 启动类 三、测试结果3.1 基于注解的控制器-测试3.2 函数式路由器-测试1添加用户接口2查询所有用户接口3根据ID查询用户接口 一、WebFlux
1.1 定义
WebFlux 是 Spring Framework 5 引入的一个模块它是一个 非阻塞的、异步的、响应式的 Web 开发框架。WebFlux 设计的核心是为了 使用现代 Web 应用对于高并发、低延迟和高吞吐量的需求它采用 Reactive 编程模型通过 Reactor 库实现了异步数据流处理。
在 WebFlux 中HTTP 请求和响应被建模为 Mono代表 0~1 个元素的异步序列和 Flux代表 0~N个元素的异步序列类型这些都是 Reactive Streams 规范的一部分。这意味着 开发者可以通过声明式和函数式编程风格来处理请求和响应的数据流。
WebFlux 提供了两种编程模型
注解式控制器 使用 Controller 等注解类似 Spring MVC 的开发体验。函数式编程控制器 使用 Java 8 函数式接口定义路由和处理逻辑。
1.2 WebFlux 与 Spring MVC 区别
WebFlux
异步非阻塞 WebFlux 基于反应式编程模型支持非阻塞 I/O能够充分利用多核 CPU 资源并且在高并发场景下具有更好的性能表现因为 它不会为每个请求分配独立的线程从而避免了线程上下文切换带来的开销。响应式编程 WebFlux 使用 Project Reactor或者 RxJava 作为备选提供的 Mono 和 Flux 类型来表示可能零个、一个或多个事件的异步序列使得开发者可以编写异步数据处理逻辑。无需 Servlet API 尽管可以在 Servlet 容器上运行但它不直接依赖 Servlet API能在非阻塞服务器如 Netty、Undertow 等上运行。函数式编程风格 除了提供类似于 Spring MVC 的注解式编程模型外WebFlux 还支持函数式编程模型允许通过 RouterFunction 等方式进行更灵活的路由配置。
Spring MVC
同步阻塞 Spring MVC 基于传统的 Servlet API每个 HTTP 请求通常都会绑定到一个单独的线程直到请求处理完成并发送响应为止。线程模型 在默认情况下Spring MVC 应用中每个请求会创建或从线程池获取一个线程处理完成后释放回线程池。这种模式在请求处理复杂度较高或线程池大小受限时可能会影响系统的并发能力。依赖 Servlet 容器 Spring MVC 必须部署在支持 Servlet API 的容器中运行如Tomcat、Jetty、Undertow、Weblogic等。API 和编程模型 Spring MVC 主要采用注解驱动的方式组织控制器和处理请求响应例如通过 Controller、RequestMapping 等注解。 二、代码实现
2.1 Maven 配置
!-- WebFlux --
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId
/dependency2.2 暴露 RESTful API 接口的方式
在 Spring WebFlux 框架中暴露 RESTful API 接口主要有以下两种方式
方式一基于注解的控制器
使用 RestController 注解定义一个控制器类通过 RequestMapping、GetMapping、PostMapping 等注解来指定请求路径和 HTTP 方法处理客户端的请求和响应。
DemoController.java
import com.demo.service.DemoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import javax.annotation.Resource;/*** p Title DemoController* p Description 测试Controller** author ACGkaka* date 2023/4/24 18:02*/
Slf4j
RestController
RequestMapping(/demo)
public class DemoController {Resourceprivate DemoService demoService;/*** webflux接口测试返回 0个 或 1个结果*/GetMapping(/monoTest)public MonoObject monoTest() {/// 写法一命令式写法
// String data getOneResult(monoTest());
// return Mono.just(data);// 写法二响应式写法语句需要在流中执行return Mono.create(cityMonoSink - {String data demoService.getOneResult(monoTest());cityMonoSink.success(data);});}/*** webflux接口测试返回 0个 或 多个结果*/GetMapping(/fluxTest)public FluxObject fluxTest() {// 写法一命令式写法
// ListString list getMultiResult(fluxTest());
// return Flux.fromIterable(list);// 写法二响应式写法语句需要在流中执行return Flux.fromIterable(demoService.getMultiResult(fluxTest()));}}方式二函数式路由器Functional Endpoints
使用 RouterFunctions.route() 或者 RouterFunctionServerResponse 来创建路由函数这种方式更加函数式和声明式。
RouteConfig.java
import com.demo.config.handler.UserReactiveHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;import javax.annotation.Resource;import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;/*** p Title RouteConfig* p Description 路由配置** author ACGkaka* date 2024/3/21 13:39*/
Configuration
public class RouteConfig {Resourceprivate UserReactiveHandler handler;Beanpublic RouterFunctionServerResponse routes() {// 下面的操作相当于 RequestMappingreturn RouterFunctions.route(POST(/addUser), handler::addUser).andRoute(GET(/userList), handler::userList).andRoute(GET(/findUserById/{id}), handler::findUserById);}
}2.3 测试Service
DemoService.java
import java.util.List;/*** p Title DemoService* p Description 测试Service** author ACGkaka* date 2024/3/20 11:46*/
public interface DemoService {/*** 模拟业务处理返回单个结果*/String getOneResult(String methodName);/*** 模拟业务处理返回多个结果*/ListString getMultiResult(String methodName);/*** 添加用户*/User addUser(User user);/*** 查询所有用户*/ListUser findAllUser();/*** 根据 id 查询用户*/User findUserById(Long id);}2.4 测试ServiceImpl
DemoServiceImpl.java
import com.demo.entity.User;
import com.demo.service.DemoService;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;/*** p Title DemoServiceImpl* p Description 测试ServiceImpl** author ACGkaka* date 2024/3/20 11:46*/
Service
public class DemoServiceImpl implements DemoService {Overridepublic String getOneResult(String methodName) {// 模拟业务处理返回单个结果return String.format(%s方法调用成功, methodName);}Overridepublic ListString getMultiResult(String methodName) {// 模拟业务处理返回多个结果ListString list new ArrayList(3);for (int i 0; i 3; i) {list.add(String.format(%s方法调用成功第 %d 条, methodName, i 1));}return list;}Overridepublic User addUser(User user) {// 添加用户user.setId(1L);return user;}Overridepublic ListUser findAllUser() {// 查询所有用户ListUser list new ArrayList();for (int i 0; i 3; i) {int no i 1;list.add(new User((long) no, USER_ no, PWD_ no, 18 no));}return list;}Overridepublic User findUserById(Long id) {// 根据 id 查询用户return new User(id, USER_ id, PWD_ id, 18);}
}2.5 测试实体类
User.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** p Title User* p Description 用户信息** author ACGkaka* date 2024/3/21 11:12*/
Data
NoArgsConstructor
AllArgsConstructor
public class User {/*** 主键*/private Long id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 年龄*/private Integer age;
}2.6 启动类
SpringbootDemoApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;SpringBootApplication
public class SpringbootDemoApplication {/*** 可以使用以下两种方式创建 ApplicationContext*/public static void main(String[] args) {// 方式一SpringApplication.run(SpringbootDemoApplication.class, args);// 方式二使用 SpringApplicationBuilder 来创建 SpringApplication。// builder 提供了链式调用 API更加方便可读性更强。
// SpringApplicationBuilder builder new SpringApplicationBuilder()
// .web(WebApplicationType.REACTIVE).sources(SpringbootDemoApplication.class);
// builder.run(args);}}三、测试结果
3.1 基于注解的控制器-测试
MonoT 返回类型的接口测试 请求地址 http://localhost:8080/demo/monoTest 请求结果 FluxT 返回类型的接口测试
请求地址 http://localhost:8080/demo/fluxTest请求结果 3.2 函数式路由器-测试
1添加用户接口
请求地址 http://localhost:8080/addUser请求结果失败测试 请求结果成功测试 2查询所有用户接口
请求地址 http://localhost:8080/userList请求结果 3根据ID查询用户接口
请求地址 http://localhost:8080/findUserById/123请求结果 整理完毕完结撒花~ 参考地址
1.webflux springboot 整合史上最全https://blog.csdn.net/crazymakercircle/article/details/112977951