Spring学习(六):WebFlux

article/2025/8/28 23:12:59

文章目录

    • WebFlux概述
      • 简介
      • 异步非阻塞
    • 响应式编程
      • 简介
      • Reactor实现
        • 简介
        • 三种信号特点
        • 操作符
        • 示例代码
    • SpringWebflux执行流程和核心API
      • 执行流程
      • 核心API
    • SpringWebflux基于注解编程
    • SpringWebflux基于函数式编程
      • 具体步骤
      • 示例代码

WebFlux概述

简介

  • WebFlux是Spring5新添加的模块以用于web开发,功能和SpringMVC类似。
  • Webflux使用响应式编程的框架。
  • Webflux 是一种异步非阻塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于Reactor的相关 API 实现的。

异步非阻塞

异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步。
阻塞和非阻塞针对被调用者,被调用者收到请求之后,做完请求任务之后才给出反馈就是阻塞,收到请求之后马上给出反馈然后再去做事情就是非阻塞。

响应式编程

简介

响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便
地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。比如Excel表格中的公式,公式的值会随着单元格的变化而变化。
Java8提供观察者模式两个类Observer和Observable,Java9提供Flow类实现响应式编程。

Reactor实现

简介

  • Reactor是满足Reactive规范的框架
  • Reactor有Mono和Flux两个核心类,这两个类都实现了Publisher接口,提供丰富操作符。Flux对象实现发布者,返回 N 个元素;Mono实现发布者,返回 0 或者1个元素
  • Flux 和 Mono 都是数据流的发布者,使用 Flux 和 Mono 都可以发出三种数据信号:元素值,错误信号,完成信号
    错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了。错误信号终止数据流同时把错误信息传递给订阅者

三种信号特点

  • 错误信号和完成信号都是终止信号,不能共存的
  • 如果没有发送任何元素值,而是直接发送错误或者完成信号,表示是空数据流
  • 如果没有错误信号,没有完成信号,表示是无限数据流

操作符

对数据流进行一道道操作成为操作符,比如工厂流水线。

  • map元素映射为新元素
    在这里插入图片描述
    比如上图对1、2和3进行了平方操作然后输出
  • flatMap元素映射为流
    把每个元素转换流,把转换之后多个流合并大的流
    在这里插入图片描述

示例代码

# 引入依赖
<dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId><version>3.1.5.RELEASE</version>
</dependency>
public static void main(String[] args) {//just 方法直接声明
Flux.just(1,2,3,4).subscribe(System.out::println);
Mono.just(1).subscribe(System.out::print);//其他的方法(集合和流)Integer[] array = {1,2,3,4};Flux.fromArray(array);List<Integer> list = Arrays.asList(array);Flux.fromIterable(list);Stream<Integer> stream = list.stream();Flux.fromStream(stream);
}

SpringWebflux执行流程和核心API

SpringWebflux基于 Reactor,默认使用容器是 Netty,Netty是高性能的 NIO(同步非阻
塞) 框架。

执行流程

SpringWebflux核心控制器DispatchHandler,实现接口WebHandler,接口中有个handler方法:

public interface WebHandler {Mono<Void> handle(ServerWebExchange var1);
}
public Mono<Void> handle(ServerWebExchange exchange) {// exchange放http请求信息return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {return mapping.getHandler(exchange);//根据请求地址获取对应mapping}).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {return this.invokeHandler(exchange, handler);//调用具体的业务方法}).flatMap((result) -> {return this.handleResult(exchange, result);//处理结果返回});
}

核心API

SpringWebflux里面DispatcherHandler类负责请求的处理,具体如下:

  • HandlerMapping
    请求查询到处理的方法
  • HandlerAdapter
    真正负责请求处理
  • HandlerResultHandler
    响应结果处理

SpringWebflux 实现函数式编程,两个接口:

  • RouterFunction
    路由处理
  • HandlerFunction
    处理函数

SpringWebflux基于注解编程

SpringWebflux 使用注解编程模型方式,和之前 SpringMVC 使用相似的,只需要把相关依赖配置到项目中,SpringBoot自动配置相关运行容器,默认情况下使用 Netty服务器。SpringMVC和SpringWebflux对比如下:

  • SpringMVC 方式实现,同步阻塞的方式,基于SpringMVC+Servlet+Tomcat
  • SpringWebflux 方式实现,异步非阻塞 方式,基于SpringWebflux+Reactor+Netty

示例代码如下:
这是SpringBoot+Maven项目,需要引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

项目结构图:

│
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─webflux
│  │  │          └─demo
│  │  │              │  WebfluxdemoApplication.java
│  │  │              │
│  │  │              ├─controller
│  │  │              │      UserController.java
│  │  │              │
│  │  │              ├─entity
│  │  │              │      User.java
│  │  │              │
│  │  │              └─service
│  │  │                  │  UserService.java
│  │  │                  │
│  │  │                  └─impl
│  │  │                          UserServiceImpl.java
│  │  │
│  │  └─resources
│  │          application.properties

User类:

public class User {private String name;private String gender;private Integer age;public User(String name, String gender, Integer age) {this.name = name;this.gender = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}

UserService接口:

public interface UserService {//根据 id 查询用户Mono<User> getUserById(int id);//查询所有用户Flux<User> getAllUser();//添加用户Mono<Void> saveUserInfo(Mono<User> user);
}

UserServiceImpl类:

@Service
public class UserServiceImpl implements UserService {//创建 map 集合存储数据private final Map<Integer,User> users = new HashMap<>();public UserServiceImpl() {this.users.put(1,new User("lucy","female",20));this.users.put(2,new User("mary","female",25));this.users.put(3,new User("jack","male",30));}//根据 id 查询@Overridepublic Mono<User> getUserById(int id) {return Mono.justOrEmpty(this.users.get(id));}//查询多个用户@Overridepublic Flux<User> getAllUser() {return Flux.fromIterable(this.users.values());}//添加用户@Overridepublic Mono<Void> saveUserInfo(Mono<User> userMono) {return userMono.doOnNext(person -> {//向 map 集合里面放值int id = users.size()+1;users.put(id,person);}).thenEmpty(Mono.empty());}
}

UserController类:

@RestController
public class UserController {@Autowiredprivate UserService userService;//id 查询@GetMapping("/user/{id}")public Mono<User> geetUserId(@PathVariable int id) {return userService.getUserById(id);}//查询所有@GetMapping("/getusers")public Flux<User> getUsers() {return userService.getAllUser();}//添加@PostMapping("/saveuser")public Mono<Void> saveUser(@RequestBody User user) {Mono<User> userMono = Mono.just(user);return userService.saveUserInfo(userMono);}
}

WebfluxdemoApplication类:

@SpringBootApplication
public class WebfluxdemoApplication {public static void main(String[] args) {SpringApplication.run(WebfluxdemoApplication.class,args);}
}

application.properties:

server.port = 8081

运行结果:
在这里插入图片描述

SpringWebflux基于函数式编程

在使用函数式编程模型操作时候,需要自己初始化服务器。基于函数式编程模型时候,有两个核心接口:RouterFunction(实现路由功能,请求转发给对应的 handler)和 HandlerFunction(处理请求生成响应的函数)。核心任务定义两个函数式接口的实现并且启动需要的服务器。SpringWebflux 请 求 和 响 应 不 再 是 ServletRequest和ServletResponse ,而是ServerRequest 和 ServerResponse。

具体步骤

  • 创建Handler(在这里写具体实现方法)
  • 创建Router路由,并初始化服务器做适配
    • 创建Router路由
    • 创建服务器做适配
    • 最终调用方法(main)编写

示例代码

项目结构图:

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─webflux
│  │  │          └─demo
│  │  │              │  Server.java
│  │  │              │
│  │  │              ├─entity
│  │  │              │      User.java
│  │  │              │
│  │  │              ├─handler
│  │  │              │      UserHandler.java
│  │  │              │
│  │  │              └─service
│  │  │                  │  UserService.java
│  │  │                  │
│  │  │                  └─impl
│  │  │                          UserServiceImpl.java

entity和service代码不变,与基于注解的代码一样

UserHandler类:

public class UserHandler {private final UserService userService;public UserHandler(UserService userService) {this.userService = userService;}//根据 id 查询public Mono<ServerResponse> getUserById(ServerRequest request) {//获取 id 值int userId = Integer.valueOf(request.pathVariable("id"));//空值处理Mono<ServerResponse> notFound = ServerResponse.notFound().build();//调用 service 方法得到数据Mono<User> userMono = this.userService.getUserById(userId);//把 userMono 进行转换返回//使用 Reactor 操作符 flatMapreturnuserMono.flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(fromObject(person))).switchIfEmpty(notFound);}//查询所有public Mono<ServerResponse> getAllUsers(ServerRequest request) {//调用 service 得到结果Flux<User> users = this.userService.getAllUser();returnServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users, User.class);}//添加public Mono<ServerResponse> saveUser(ServerRequest request) {//得到 user 对象Mono<User> userMono = request.bodyToMono(User.class);returnServerResponse.ok().build(this.userService.saveUserInfo(userMono));}
}

Server类:

public class Server {//1 创建 Router 路由public RouterFunction<ServerResponse> routingFunction() {//创建 hanler 对象UserService userService = new UserServiceImpl();UserHandler handler = new UserHandler(userService);//设置路由return RouterFunctions.route(GET("/users/{id}").and(accept(APPLICATION_JSON)),handler::getUserById).andRoute(GET("/getallusers").and(accept(APPLICATION_JSON)),handler::getAllUsers);}//2 创建服务器完成适配public void createReactorServer() {//路由和 handler 适配RouterFunction<ServerResponse> route = routingFunction();HttpHandler httpHandler = toHttpHandler(route);ReactorHttpHandlerAdapter adapter = newReactorHttpHandlerAdapter(httpHandler);//创建服务器HttpServer httpServer = HttpServer.create();httpServer.handle(adapter).bindNow();}//3 最终调用方法(main)编写public static void main(String[] args) throws Exception{Server server = new Server();server.createReactorServer();System.out.println("enter to exit");System.in.read();}
}

运行main方法后效果:

16:05:18.184 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
16:05:18.184 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
16:05:18.184 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
16:05:18.204 [reactor-http-nio-1] DEBUG reactor.netty.tcp.TcpServer - [id: 0x16e3bd47, L:/0:0:0:0:0:0:0:0:51646] Bound new server
enter to exit

运行成功会有一个端口,比如我这里是51646,然后在浏览器中用这个端口请求就可以了。如下所示:
在这里插入图片描述
如有错误,欢迎指正!

点击获取Spring相关文章的MarkDown源文件(一共6个)


http://chatgpt.dhexx.cn/article/ak2fUpiK.shtml

相关文章

Spring Web vs Spring Webflux

当你需要构建Web应用程序时&#xff0c;Spring Web 和 Spring Webflux 是Spring生态系统中的两个框架&#xff0c;但它们之间有一些关键区别。 Spring Web 是一个传统的Web框架&#xff0c;它构建在Servlet API之上。它旨在处理阻塞式I/O&#xff0c;即线程在从数据库或其他服务…

Spring Boot(5)之 WebFlux 响应式编程

1、WebFlux简介 springWebFlux 是 SpringFrameworl5.0 添加的新功能&#xff0c;WebFlux 本身是追随当下最火的 Reactive Programming 而诞生的框架&#xff0c;那么本编就来简述下这个框架到底是做什么的。 参考&#xff1a;Spring-WebFlux简介与使用 1.1、关于WebFlux 我们…

对比WebFlux和WebMVC (为什么使用WebFlux)

对比WebFlux和WebMVC (为什么使用WebFlux) 1.0 WebFlux吞吐量对比WebMVC 2.0 WebFlux延迟/CPU对比WebMVC 3.0 WebFlux内存使用对比WebMVC 4.0 WebFlux最大处理请求对比WebMVC 1

Spring(十)Webflux

Webflux 1、SpringWebflux 介绍 &#xff08;1&#xff09;是 Spring5 添加新的模块&#xff0c;用于 web 开发的&#xff0c;功能和 SpringMVC 类似的&#xff0c;Webflux 使用当前一种比较流程响应式编程出现的框架。 &#xff08;2&#xff09;使用传统 web 框架&#xff…

Spring:Webflux响应式编程

目录 简介响应式编程Reactor信号操作符 SpringWebflux 执行流程和API 注解实现SpringWebflux 说明&#xff1a;基于atguigu学习笔记。 简介 Webflux是 Spring5 添加新的模块&#xff0c;用于 web 开发的&#xff0c;功能和 SpringMVC 类似的&#xff0c;Webflux 使用当前一种比…

WebFlux入门详解

文章目录 一、 WebFlux介绍1、什么是 WebFlux2、反应式库介绍2.1 Reactive Stream2.2 Reactor2.3 Reactive Stream、Reactor 和 WebFlux 关系 二、入门WebFlux1、简单介绍2、简单的例子构造 三、WebFlux与数据库1、介绍2、r2dbc实战前期准备2.1 引入依赖与配置2.2 创建数据表2.…

springboot之webmvc和webflux浅析

webmvc和webflux作为spring framework的两个重要模块&#xff0c;代表了两个IO模型&#xff0c;阻塞式和非阻塞式。 1、webmvc webmvc是基于servlet的阻塞式模型&#xff0c;一个请求到达服务器后会单独分配一个线程去处理请求&#xff0c;如果请求包含IO操作&#xff0c;线程…

Webflux核心

什么是WebFlux? Spring WebFlux 是一套全新的 Reactive Web 栈技术&#xff0c;实现完全非阻塞&#xff0c;支持 Reactive Streams 背压等特性&#xff0c;并且运行环境不限于 Servlet 容器&#xff08;Tomcat、Jetty、Undertow&#xff09;&#xff0c;如 Netty 等。Spring W…

SpringBoot Webflux解析

1. Webflux介绍 Webflux是一种异步非阻塞的IO模型&#xff0c;当有请求过来时&#xff0c;它会将请求交由worker线程去处理&#xff0c;这样就可以极大的提升吞吐量&#xff0c;所以他比较适合用于IO密集型的场景。 webflux虽然可以给我带来吞吐量的提升&#xff0c;但是同时也…

Webflux快速入门

传统的Web框架&#xff0c;如struts2&#xff0c;springmvc等都是基于Servlet API与Servlet容器基础之上运行的&#xff0c;在Servlet3.1之后才有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架&#xff0c;它的核心是基于Reactor的相关API实现的。相对于传统的web框…

Spring-webflux 响应式编程

热爱可抵漫长岁月 文章目录 1. 前言2. Spring-webflux简介3. 什么是“响应式”4. Spring-webflux的响应式API5. Spring MVC 还是 WebFlux&#xff1f;6. 并发模型7. webflux使用8. 测试 1. 前言 Spring 提供了两个并行堆栈。一种是基于带有 Spring MVC 和 Spring Data 结构的 …

Spring Webflux - 01 MVC的困境

文章目录 Spring MVC的困境Servlet 异步请求缓解线程池压力Servlet 3.0 异步请求处理Code 演示工程pom配置文件启动类同步servlet演示 异步servlet辅助Code演示 Tomcat 请求处理流程以及异步请求工作原理 Spring MVC的困境 我们先看一段工作中大家常见的代码 RestController …

WebFlux的使用

什么是WebFlux springWebFlux 是 SpringFrameworlk5.0 添加的新功能&#xff0c;它是完全非阻塞的&#xff0c;支持Reactive Stream及背压&#xff0c;可以运行于Netty、Undertow等服务器&#xff0c;及Servlet 3.1容器。 webflux主要在如下两方面体现出独有的优势&#xff1a;…

webFlux入门

今天发现一个特别好的文章&#xff0c;是关于springBoot框架中响应式编程的&#xff0c;那下面就是这位博主所整理的一些干货&#x1f447; ------------------------------------------------------------ 1. WebFlux介绍 Spring WebFlux 是 Spring Framework 5.0中引入的新…

WebFlux 简介

目录 一、关于WebFlux 二、SpringMVC与SpringWebFlux 三、Reactive Spring Web HttpHandler WebHandler 四、实现WebFlux 实例 基于Annotated Controller方式实现 WebFluxConfig配置&#xff1a; Controller: Main方法&#xff1a; 函数式编程方式 集成Thymeleaf sp…

Spring Webflux 响应式编程 (二) - WebFlux编程实战

第一章 Reactive Stream 第1节 jdk9的响应式流 就是reactive stream&#xff0c;也就是flow。其实和jdk8的stream没有一点关系。说白了就一个发布-订阅模式&#xff0c;一共只有4个接口&#xff0c;3个对象&#xff0c;非常简单清晰。 什么是背压&#xff1f; 背压是指订阅者…

WebFlux 详解

今天我们开始来学习下 WebFlux&#xff0c;为什么突然要学这个东西&#xff1f; 因为我之前是想学习 Spring Cloud Gateway 来着&#xff0c;然后发现它是基于 Spring5.0SpringBoot2.0WebFlux等技术开发的。所以学之前才要来简单了解下 WebFlux 技术。 然后要学习 WebFlux 时…

Redis常用数据类型及其对应的底层数据结构

Redis数据库 Redis是一种键值(Key-Value)数据库。相较于MySQL之类的关系型数据库&#xff0c;Redis是一种非关系型数据库。Redis存储的数据只包含键和值两部分&#xff0c;只能通过键来查询值。这样简单的存储结构&#xff0c;能让Redis的读写效率非常高(HashMap读写效率都是O…

二. Redis 数据类型

2.1 Redis 字符串 (String) 2.1.1 概述 String 是 Redis 最基本的类型&#xff0c;你可以理解成与 Memcached 一模一样的类型&#xff0c;一个 key 对应一个 value。 String 类型是二进制安全的。意味着 Redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。 …

Redis数据类型Hash

文章目录 Hash类型介绍hash 类型数据的基本操作 hash 类型数据操作的注意事项Hash和String类型的区别 有时候我们往往不是在缓存中存一个值&#xff0c;而是选择存一个对象&#xff0c;比如一个购物车消息&#xff0c;我们就需要使用到hash了 Hash类型介绍 新的存储需求&…