Spring WebFlux响应式编程如何从零开始学习?

2026-05-25 23:051阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2450个文字,预计阅读时间需要10分钟。

Spring WebFlux响应式编程如何从零开始学习?

目录+简介+响应式编程+Reactor+符号+SpringWebFlux执行流程及API+注解实现SpringWebFlux+说明:基于atguigu学习笔记。简介+WebFlux是Spring5新增的模块,用于web开发,功能和SpringMVC类似。

目录
  • 简介
  • 响应式编程
    • Reactor
      • 信号
      • 操作符
    • SpringWebflux执行流程和API
    • 注解实现SpringWebflux

      说明:基于atguigu学习笔记。

      简介

      Webflux是 Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用当前一种比较流程响应式编程出现的框架。

      使用传统 web 框架,比如 SpringMVC,这些基于 Servlet 容器,Webflux 是一种异步非阻

      塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于 Reactor 的相关 API 实现

      的。

      Webflux 特点:

      • 非阻塞式:在有限资源下,提高系统吞吐量和伸缩性,以 Reactor 为基础实现响应式编程
      • 函数式编程:Spring5 框架基于 java8,Webflux 使用 Java8 函数式编程方式实现路由请求

      比较 SpringMVC:

      第一:两个框架都可以使用注解方式,都运行在 Tomet 等容器中

      Spring WebFlux响应式编程如何从零开始学习?

      第二:SpringMVC 采用命令式编程,Webflux 采用异步响应式编程

      响应式编程

      响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化

      Reactor

      Reactor 框架是 Pivotal 基于 Reactive Programming 思想实现的。

      Reactor 有两个核心类,Mono 和 Flux,这两个类实现接口 Publisher,提供丰富操作

      符。Flux 对象实现发布者,返回 N 个元素;Mono 实现发布者,返回 0 或者 1 个元素。

      信号

      Flux 和 Mono 都是数据流的发布者,使用 Flux 和 Mono 都可以发出三种数据信号:

      元素值,错误信号,完成信号,错误信号和完成信号都代表终止信号,终止信号用于告诉

      订阅者数据流结束了,错误信号终止数据流同时把错误信息传递给订阅者。

      示例:

      1.引入依赖

      <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.1.5.RELEASE</version> </dependency>

      2.代码

      package com.example.springdemo3; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Test01 { public static void main(String[] args) { //just 方法直接声明 Flux.just(1,2,3,4); Mono.just(1); //其他的方法 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); } }

      三种信号特点

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

      调用 just 或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才会触

      发数据流,不订阅什么都不会发生。示例如下:

      package com.example.springdemo3; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Test01 { public static void main(String[] args) { //just 方法直接声明 Flux.just(1,2,3,4).subscribe(System.out::println); Mono.just(1).subscribe(System.out::println);; } }

      操作符

      操作符对数据流进行一道道操作,成为操作符,比如工厂流水线。有以下两个操作符:

      1.map

      将一个数据流里的每个元素映射为新元素,返回一个新的流。

      2.flatMap

      把每个元素转换成数据流,把转换之后多个流合并一个大的数据流

      SpringWebflux执行流程和API

      SpringWebflux 基于 Reactor,默认使用容器是 Netty,Netty 是高性能的 NIO 框架,异步非阻

      塞的框架。

      SpringWebflux 执行过程和 SpringMVC 相似的,SpringWebflux 核心控制器 DispatchHandler,实现了接口 WebHandler。WebHandler的源码如下:

      // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.web.server; import reactor.core.publisher.Mono; public interface WebHandler { Mono<Void> handle(ServerWebExchange var1); }

      可以看到只有一个方法WebHandler,WebHandler的实现在DispatcherHandler类中,实现逻辑如下:

      public Mono<Void> handle(ServerWebExchange exchange) { return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> { return mapping.getHandler(exchange); }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> { return this.invokeHandler(exchange, handler); }).flatMap((result) -> { return this.handleResult(exchange, result); }); }

      其中,参数ServerWebExchange是放maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-demo3</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-demo3</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.7.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.example.springdemo3.SpringDemo3Application</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

      2.创建包和相关类

      实体类:

      package com.example.springdemo3.entity; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class User { private String name; private String gender; private Integer age; }

      service接口:

      package com.example.springdemo3.service; import com.example.springdemo3.entity.User; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public interface UserService { //根据 id 查询用户 Mono<User> getUserById(int id); //查询所有用户 Flux<User> getAllUser(); //添加用户 Mono<Void> saveUserInfo(Mono<User> user); }

      service实现类

      package com.example.springdemo3.service.impl; import com.example.springdemo3.entity.User; import com.example.springdemo3.service.UserService; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.HashMap; import java.util.Map; @Service public class UserServiceImpl implements UserService { //创建 map 集合存储数据 private final Map<Integer,User> users = new HashMap<>(); public UserServiceImpl() { this.users.put(1,new User("lucy","nan",20)); this.users.put(2,new User("mary","nv",30)); this.users.put(3,new User("jack","nv",50)); } @Override public Mono<User> getUserById(int id) { return Mono.justOrEmpty(this.users.get(id)); } @Override public Flux<User> getAllUser() { return Flux.fromIterable(this.users.values()); } @Override public Mono<Void> saveUserInfo(Mono<User> userMono) { return userMono.doOnNext(person -> { //向 map 集合里面放值 int id = users.size()+1; users.put(id,person); }).thenEmpty(Mono.empty()); // Mono.empty()是终止信号 } }

      注意这里没有真正和数据库交互,而是维护了一个数组,模拟数据库。

      controller类:

      package com.example.springdemo3.controller; import com.example.springdemo3.entity.User; import com.example.springdemo3.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Component @RestController public class UserController { //注入 service @Autowired private UserService userService; //id 查询 @GetMapping("/user/{id}") public Mono<User> geetUserId(@PathVariable int id) { return userService.getUserById(id); } //查询所有 @GetMapping("/user") 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); } }

      SpringMVC 方式实现,同步阻塞的方式,基于 SpringMVC+Servlet+Tomcat

      SpringWebflux 方式实现,异步非阻塞 方式,基于 SpringWebflux+Reactor+Netty

      到此这篇关于Spring零基础入门WebFlux响应式编程的文章就介绍到这了,更多相关Spring WebFlux内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

      本文共计2450个文字,预计阅读时间需要10分钟。

      Spring WebFlux响应式编程如何从零开始学习?

      目录+简介+响应式编程+Reactor+符号+SpringWebFlux执行流程及API+注解实现SpringWebFlux+说明:基于atguigu学习笔记。简介+WebFlux是Spring5新增的模块,用于web开发,功能和SpringMVC类似。

      目录
      • 简介
      • 响应式编程
        • Reactor
          • 信号
          • 操作符
        • SpringWebflux执行流程和API
        • 注解实现SpringWebflux

          说明:基于atguigu学习笔记。

          简介

          Webflux是 Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用当前一种比较流程响应式编程出现的框架。

          使用传统 web 框架,比如 SpringMVC,这些基于 Servlet 容器,Webflux 是一种异步非阻

          塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于 Reactor 的相关 API 实现

          的。

          Webflux 特点:

          • 非阻塞式:在有限资源下,提高系统吞吐量和伸缩性,以 Reactor 为基础实现响应式编程
          • 函数式编程:Spring5 框架基于 java8,Webflux 使用 Java8 函数式编程方式实现路由请求

          比较 SpringMVC:

          第一:两个框架都可以使用注解方式,都运行在 Tomet 等容器中

          Spring WebFlux响应式编程如何从零开始学习?

          第二:SpringMVC 采用命令式编程,Webflux 采用异步响应式编程

          响应式编程

          响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化

          Reactor

          Reactor 框架是 Pivotal 基于 Reactive Programming 思想实现的。

          Reactor 有两个核心类,Mono 和 Flux,这两个类实现接口 Publisher,提供丰富操作

          符。Flux 对象实现发布者,返回 N 个元素;Mono 实现发布者,返回 0 或者 1 个元素。

          信号

          Flux 和 Mono 都是数据流的发布者,使用 Flux 和 Mono 都可以发出三种数据信号:

          元素值,错误信号,完成信号,错误信号和完成信号都代表终止信号,终止信号用于告诉

          订阅者数据流结束了,错误信号终止数据流同时把错误信息传递给订阅者。

          示例:

          1.引入依赖

          <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.1.5.RELEASE</version> </dependency>

          2.代码

          package com.example.springdemo3; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Test01 { public static void main(String[] args) { //just 方法直接声明 Flux.just(1,2,3,4); Mono.just(1); //其他的方法 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); } }

          三种信号特点

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

          调用 just 或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才会触

          发数据流,不订阅什么都不会发生。示例如下:

          package com.example.springdemo3; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Test01 { public static void main(String[] args) { //just 方法直接声明 Flux.just(1,2,3,4).subscribe(System.out::println); Mono.just(1).subscribe(System.out::println);; } }

          操作符

          操作符对数据流进行一道道操作,成为操作符,比如工厂流水线。有以下两个操作符:

          1.map

          将一个数据流里的每个元素映射为新元素,返回一个新的流。

          2.flatMap

          把每个元素转换成数据流,把转换之后多个流合并一个大的数据流

          SpringWebflux执行流程和API

          SpringWebflux 基于 Reactor,默认使用容器是 Netty,Netty 是高性能的 NIO 框架,异步非阻

          塞的框架。

          SpringWebflux 执行过程和 SpringMVC 相似的,SpringWebflux 核心控制器 DispatchHandler,实现了接口 WebHandler。WebHandler的源码如下:

          // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.web.server; import reactor.core.publisher.Mono; public interface WebHandler { Mono<Void> handle(ServerWebExchange var1); }

          可以看到只有一个方法WebHandler,WebHandler的实现在DispatcherHandler类中,实现逻辑如下:

          public Mono<Void> handle(ServerWebExchange exchange) { return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> { return mapping.getHandler(exchange); }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> { return this.invokeHandler(exchange, handler); }).flatMap((result) -> { return this.handleResult(exchange, result); }); }

          其中,参数ServerWebExchange是放maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-demo3</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-demo3</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.7.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.example.springdemo3.SpringDemo3Application</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

          2.创建包和相关类

          实体类:

          package com.example.springdemo3.entity; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class User { private String name; private String gender; private Integer age; }

          service接口:

          package com.example.springdemo3.service; import com.example.springdemo3.entity.User; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public interface UserService { //根据 id 查询用户 Mono<User> getUserById(int id); //查询所有用户 Flux<User> getAllUser(); //添加用户 Mono<Void> saveUserInfo(Mono<User> user); }

          service实现类

          package com.example.springdemo3.service.impl; import com.example.springdemo3.entity.User; import com.example.springdemo3.service.UserService; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.HashMap; import java.util.Map; @Service public class UserServiceImpl implements UserService { //创建 map 集合存储数据 private final Map<Integer,User> users = new HashMap<>(); public UserServiceImpl() { this.users.put(1,new User("lucy","nan",20)); this.users.put(2,new User("mary","nv",30)); this.users.put(3,new User("jack","nv",50)); } @Override public Mono<User> getUserById(int id) { return Mono.justOrEmpty(this.users.get(id)); } @Override public Flux<User> getAllUser() { return Flux.fromIterable(this.users.values()); } @Override public Mono<Void> saveUserInfo(Mono<User> userMono) { return userMono.doOnNext(person -> { //向 map 集合里面放值 int id = users.size()+1; users.put(id,person); }).thenEmpty(Mono.empty()); // Mono.empty()是终止信号 } }

          注意这里没有真正和数据库交互,而是维护了一个数组,模拟数据库。

          controller类:

          package com.example.springdemo3.controller; import com.example.springdemo3.entity.User; import com.example.springdemo3.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Component @RestController public class UserController { //注入 service @Autowired private UserService userService; //id 查询 @GetMapping("/user/{id}") public Mono<User> geetUserId(@PathVariable int id) { return userService.getUserById(id); } //查询所有 @GetMapping("/user") 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); } }

          SpringMVC 方式实现,同步阻塞的方式,基于 SpringMVC+Servlet+Tomcat

          SpringWebflux 方式实现,异步非阻塞 方式,基于 SpringWebflux+Reactor+Netty

          到此这篇关于Spring零基础入门WebFlux响应式编程的文章就介绍到这了,更多相关Spring WebFlux内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!