今天发现一个特别好的文章,是关于springBoot框架中响应式编程的,那下面就是这位博主所整理的一些干货

------------------------------------------------------------

1. WebFlux介绍

Spring WebFlux 是 Spring Framework 5.0中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。

Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。

(PS:所谓异步非阻塞是针对服务端而言的,是说服务端可以充分利用CPU资源去做更多事情,这与客户端无关,客户端该怎么请求还是怎么请求。)

Reactive Streams是一套用于构建高吞吐量、低延迟应用的规范。而Reactor项目是基于这套规范的实现,它是一个完全非阻塞的基础,且支持背压。Spring WebFlux基于Reactor实现了完全异步非阻塞的一套web框架,是一套响应式堆栈。

【spring-webmvc + Servlet + Tomcat】命令式的、同步阻塞的

【spring-webflux + Reactor + Netty】响应式的、异步非阻塞的

2. Spring WebFlux Framework

Spring WebFlux有两种风格:功能性和基于注释的。基于注释的与Spring MVC非常相近。例如:

 1 @RestController
2 @RequestMapping("/users")
3 public class MyRestController {
4
5 @GetMapping("/{user}")
6 public Mono<User> getUser(@PathVariable Long user) {
7 // ...
8 }
9
10 @GetMapping("/{user}/customers")
11 public Flux<Customer> getUserCustomers(@PathVariable Long user) {
12 // ...
13 }
14
15 @DeleteMapping("/{user}")
16 public Mono<User> deleteUser(@PathVariable Long user) {
17 // ...
18 }
19 } 

与之等价,也可以这样写:

 1 @Configuration
2 public class RoutingConfiguration {
3 @Bean
4 public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
5 return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
6 .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
7 .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
8 }
9 }
10
11 @Component
12 public class UserHandler {
13 public Mono<ServerResponse> getUser(ServerRequest request) {
14 // ...
15 }
16 public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
17 // ...
18 }
19 public Mono<ServerResponse> deleteUser(ServerRequest request) {
20 // ...
21 }
22 }

如果你同时添加了spring-boot-starter-web和spring-boot-starter-webflux依赖,那么Spring Boot会自动配置Spring MVC,而不是WebFlux。你当然可以强制指定应用类型,通过SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)

3. Hello WebFlux

pom.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.2.5.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>com.cjs.example</groupId>
12 <artifactId>cjs-reactive-rest-service</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>cjs-reactive-rest-service</name>
15
16 <properties>
17 <java.version>1.8</java.version>
18 </properties>
19
20 <dependencies>
21 <dependency>
22 <groupId>org.springframework.boot</groupId>
23 <artifactId>spring-boot-starter-webflux</artifactId>
24 </dependency>
25
26 <dependency>
27 <groupId>org.springframework.boot</groupId>
28 <artifactId>spring-boot-starter-test</artifactId>
29 <scope>test</scope>
30 <exclusions>
31 <exclusion>
32 <groupId>org.junit.vintage</groupId>
33 <artifactId>junit-vintage-engine</artifactId>
34 </exclusion>
35 </exclusions>
36 </dependency>
37 <dependency>
38 <groupId>io.projectreactor</groupId>
39 <artifactId>reactor-test</artifactId>
40 <scope>test</scope>
41 </dependency>
42 </dependencies>
43
44 <build>
45 <plugins>
46 <plugin>
47 <groupId>org.springframework.boot</groupId>
48 <artifactId>spring-boot-maven-plugin</artifactId>
49 </plugin>
50 </plugins>
51 </build>
52
53 </project>

GreetingHandler.java

 1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.http.MediaType;
4 import org.springframework.stereotype.Component;
5 import org.springframework.web.reactive.function.BodyInserters;
6 import org.springframework.web.reactive.function.server.ServerRequest;
7 import org.springframework.web.reactive.function.server.ServerResponse;
8 import reactor.core.publisher.Mono;
9
10 import java.util.concurrent.atomic.AtomicLong;
11
12 /**
13 * @author ChengJianSheng
14 * @date 2020-03-25
15 */
16 @Component
17 public class GreetingHandler {
18
19 private final AtomicLong counter = new AtomicLong();
20
21 /**
22 * A handler to handle the request and create a response
23 */
24 public Mono<ServerResponse> hello(ServerRequest request) {
25 return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
26 .body(BodyInserters.fromValue("Hello, Spring!"));
27
28 }
29 }

GreetingRouter.java

 1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.context.annotation.Bean;
4 import org.springframework.context.annotation.Configuration;
5 import org.springframework.http.MediaType;
6 import org.springframework.web.reactive.function.server.*;
7
8 /**
9 * @author ChengJianSheng
10 * @date 2020-03-25
11 */
12 @Configuration
13 public class GreetingRouter {
14
15 /**
16 * The router listens for traffic on the /hello path and returns the value provided by our reactive handler class.
17 */
18 @Bean
19 public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
20 return RouterFunctions.route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), greetingHandler::hello);
21 }
22 }

GreetingWebClient.java

 1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.http.MediaType;
4 import org.springframework.web.reactive.function.client.ClientResponse;
5 import org.springframework.web.reactive.function.client.WebClient;
6 import reactor.core.publisher.Mono;
7
8 /**
9 * @author ChengJianSheng
10 * @date 2020-03-25
11 */
12 public class GreetingWebClient {
13
14 /**
15 * For reactive applications, Spring offers the WebClient class, which is non-blocking.
16 *
17 * WebClient can be used to communicate with non-reactive, blocking services, too.
18 */
19 private WebClient client = WebClient.create("http://localhost:8080");
20
21 private Mono<ClientResponse> result = client.get()
22 .uri("/hello")
23 .accept(MediaType.TEXT_PLAIN)
24 .exchange();
25
26 public String getResult() {
27 return ">> result = " + result.flatMap(res -> res.bodyToMono(String.class)).block();
28 }
29 }

Application.java

 1 package com.cjs.example.restservice;
2
3 import com.cjs.example.restservice.hello.GreetingWebClient;
4 import org.springframework.boot.SpringApplication;
5 import org.springframework.boot.autoconfigure.SpringBootApplication;
6
7 /**
8 * @author ChengJianSheng
9 * @date 2020-03-25
10 */
11 @SpringBootApplication
12 public class CjsReactiveRestServiceApplication {
13
14 public static void main(String[] args) {
15 SpringApplication.run(CjsReactiveRestServiceApplication.class, args);
16
17 GreetingWebClient gwc = new GreetingWebClient();
18 System.out.println(gwc.getResult());
19 }
20
21 } 

可以直接在浏览器中访问 http://localhost:8080/hello

GreetingRouterTest.java

 1 package com.cjs.example.restservice;
2
3 import org.junit.jupiter.api.Test;
4 import org.junit.jupiter.api.extension.ExtendWith;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.boot.test.context.SpringBootTest;
7 import org.springframework.http.MediaType;
8 import org.springframework.test.context.junit.jupiter.SpringExtension;
9 import org.springframework.test.web.reactive.server.WebTestClient;
10
11 @ExtendWith(SpringExtension.class)
12 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
13 public class GreetingRouterTest {
14
15 @Autowired
16 private WebTestClient webTestClient;
17
18 /**
19 * Create a GET request to test an endpoint
20 */
21 @Test
22 public void testHello() {
23 webTestClient.get()
24 .uri("/hello")
25 .accept(MediaType.TEXT_PLAIN)
26 .exchange()
27 .expectStatus().isOk()
28 .expectBody(String.class).isEqualTo("Hello, Spring!");
29 }
30
31 }

4. Reactor 核心特性

Mono: implements Publisher and returns 0 or 1 elements

Flux: implements Publisher and returns N elements

5. Spring Data Redis

pom.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.2.6.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>com.cjs.example</groupId>
12 <artifactId>cjs-webflux-hello</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>cjs-webflux-hello</name>
15
16 <properties>
17 <java.version>1.8</java.version>
18 </properties>
19
20 <dependencies>
21 <dependency>
22 <groupId>org.springframework.boot</groupId>
23 <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
24 </dependency>
25 <dependency>
26 <groupId>org.springframework.boot</groupId>
27 <artifactId>spring-boot-starter-webflux</artifactId>
28 </dependency>
29
30 <dependency>
31 <groupId>org.apache.commons</groupId>
32 <artifactId>commons-pool2</artifactId>
33 <version>2.8.0</version>
34 </dependency>
35 <dependency>
36 <groupId>com.alibaba</groupId>
37 <artifactId>fastjson</artifactId>
38 <version>1.2.67</version>
39 </dependency>
40 <dependency>
41 <groupId>org.projectlombok</groupId>
42 <artifactId>lombok</artifactId>
43 <optional>true</optional>
44 </dependency>
45 <dependency>
46 <groupId>org.springframework.boot</groupId>
47 <artifactId>spring-boot-starter-test</artifactId>
48 <scope>test</scope>
49 <exclusions>
50 <exclusion>
51 <groupId>org.junit.vintage</groupId>
52 <artifactId>junit-vintage-engine</artifactId>
53 </exclusion>
54 </exclusions>
55 </dependency>
56 <dependency>
57 <groupId>io.projectreactor</groupId>
58 <artifactId>reactor-test</artifactId>
59 <scope>test</scope>
60 </dependency>
61 </dependencies>
62
63 <build>
64 <plugins>
65 <plugin>
66 <groupId>org.springframework.boot</groupId>
67 <artifactId>spring-boot-maven-plugin</artifactId>
68 </plugin>
69 </plugins>
70 </build>
71
72 </project>

UserController.java

 1 package com.cjs.example.webflux.controller;
2
3 import com.alibaba.fastjson.JSON;
4 import com.cjs.example.webflux.domain.User;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.data.redis.core.ReactiveHashOperations;
7 import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
8 import org.springframework.web.bind.annotation.*;
9 import reactor.core.publisher.Mono;
10
11 /**
12 * @author ChengJianSheng
13 * @date 2020-03-27
14 */
15 @RestController
16 @RequestMapping("/users")
17 public class UserController {
18
19
20 @Autowired
21 private ReactiveStringRedisTemplate reactiveStringRedisTemplate;
22
23 @GetMapping("/hello")
24 public Mono<String> hello() {
25 return Mono.just("Hello, Reactive");
26 }
27
28 @PostMapping("/save")
29 public Mono<Boolean> saveUser(@RequestBody User user) {
30 ReactiveHashOperations hashOperations = reactiveStringRedisTemplate.opsForHash();
31 return hashOperations.put("USER_HS", String.valueOf(user.getId()), JSON.toJSONString(user));
32 }
33
34 @GetMapping("/info/{id}")
35 public Mono<User> info(@PathVariable Integer id) {
36 ReactiveHashOperations reactiveHashOperations = reactiveStringRedisTemplate.opsForHash();
37 Mono<String> hval = reactiveHashOperations.get("USER_HS", String.valueOf(id));
38 return hval.map(e->JSON.parseObject(e, User.class));
39 }
40
41 }

CoffeeController.java

 1 package com.cjs.example.webflux.controller;
2
3 import com.cjs.example.webflux.domain.Coffee;
4 import org.springframework.data.redis.core.*;
5 import org.springframework.web.bind.annotation.GetMapping;
6 import org.springframework.web.bind.annotation.PathVariable;
7 import org.springframework.web.bind.annotation.RequestMapping;
8 import org.springframework.web.bind.annotation.RestController;
9 import reactor.core.publisher.Flux;
10 import reactor.core.publisher.Mono;
11
12 /**
13 * Spring WebFlux is the new reactive web framework introduced in Spring Framework 5.0.
14 * Unlike Spring MVC, it does not require the Servlet API, is fully asynchronous and non-blocking,
15 * and implements the Reactive Streams specification through the Reactor project.
16 *
17 * @author ChengJianSheng
18 * @date 2020-03-27
19 */
20 @RestController
21 @RequestMapping("/coffees")
22 public class CoffeeController {
23
24 private final ReactiveRedisOperations<String, Coffee> coffeeOps;
25
26 public CoffeeController(ReactiveRedisOperations<String, Coffee> coffeeOps) {
27 this.coffeeOps = coffeeOps;
28 }
29
30 @GetMapping("/getAll")
31 public Flux<Coffee> getAll() {
32 return coffeeOps.keys("*").flatMap(coffeeOps.opsForValue()::get);
33 }
34
35 @GetMapping("/info/{id}")
36 public Mono<Coffee> info(@PathVariable String id) {
37 ReactiveValueOperations valueOperations = coffeeOps.opsForValue();
38 return valueOperations.get(id);
39 }
40 } 

最后,也是非常重要的一点:异步非阻塞并不会使程序运行得更快。WebFlux 并不能使接口的响应时间缩短,它仅仅能够提升吞吐量和伸缩性。

Spring WebFlux 是一个异步非阻塞的 Web 框架,所以,它特别适合应用在 IO 密集型的服务中,比如微服务网关这样的应用中。

Reactive and non-blocking generally do not make applications run faster.

6. Docs

Spring | Home

Spring | Reactive

Reactor 3 Reference Guide

Reactor 3 Reference Guide

Index of /spring-framework/docs

Spring Framework Documentation

Web on Reactive Stack

Web on Reactive Stack

转载自:https://www.cnblogs.com/cjsblog/p/12580518.html

原作者:废物大师兄

webFlux入门的更多相关文章

  1. (转)Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门

    http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html Spring 5.0 中发布了重量级组件 Webflux ...

  2. Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门

    Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕. WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统 ...

  3. springboot 学习之路 17(webflux 入门 (1))

    Webflux: webflux是在springboot2系列引入的技术:补充一些概念: 1> Reactive Streams 是 JVM 中面向流的库标准和规范: 处理可能无限数量的元素 按 ...

  4. Spring WebFlux 入门

    1. WebFlux介绍 Spring WebFlux 是 Spring Framework 5.0中引入的新的响应式web框架.与Spring MVC不同,它不需要Servlet API,是完全异步 ...

  5. spring boot(一):入门篇

    构建微服务:Spring boot 入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

  6. Webflux(史上最全)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  7. Spring Boot 2.0 WebFlux 教程 (一) | 入门篇

    目录 一.什么是 Spring WebFlux 二.WebFlux 的优势&提升性能? 三.WebFlux 应用场景 四.选 WebFlux 还是 Spring MVC? 五.异同点 六.简单 ...

  8. Spring Boot WebFlux 快速入门实践

    02:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ( ...

  9. Spring Boot 2 快速教程:WebFlux 快速入门(二)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 02:WebFlux 快速入门实践 文章工程: JDK 1.8 ...

  10. Spring Boot WebFlux-01——WebFlux 快速入门实践

    第01课:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ...

随机推荐

  1. 【Linux】3.10 进程管理(重点)

    进程管理 1. 进程管理基础 在Linux中,每个执行的程序(代码)都称为一个进程.每个进程都分配一个ID号 每一个进程,都会对应一个父进程,而这个父进程可以复制多个子进程.例如www服务器. 每个进 ...

  2. IE 条件注释

    参考文档 IE6 IE7 IE8 IE9 IE10 Css hack及IE条件注释法 IE的有条件注释判定IE版本详解(附实例代码)

  3. Python实验1 温度转换与输入输出强化

    实验任务: 实现摄氏温度与华氏温度互转(保留两位小数) 扩展功能:输入错误处理(如非数字输入提示重新输入) 扩展:支持开尔文温度的三向转换 源代码:def c_to_f(c): return c * ...

  4. MySQL 高可用集群搭建部署

    MySQL 高可用集群搭建(GTID 模式 + 自动故障转移) 一.环境规划 角色 IP 地址 说明 主库 (Master) 192.168.1.100 运行 MySQL + Keepalived/M ...

  5. 代码随想录第九天 | Leecode 151.翻转字符串里的单词、Leecode 28. 找出字符串中第一个匹配项的下标、Leecode 459.重复的子字符串

    Leecode 151.翻转字符串里的单词 题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/description/ 题目描述 ...

  6. 设计模式之“状态模式(State)”(未完整)

    一.状态模式(State) 状态模式是当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类 二.状态模式的作用 状态模式主要解决的是当控制一个对象状态转换条件表达式过于复杂时的情况. ...

  7. Plotting and visualization through matplotlib and pandas

    Plotting and visualization through matplotlib and pandas %matplotlib notebook import matplotlib.pypl ...

  8. No grammar constraints (DTD or XML schema) detected for the document

    warning: No grammar constraints (DTD or XML schema) detected for the document 未检测到文档的语法约束(DTD或XML模式) ...

  9. WindowsPE文件格式入门08.导出表

    https://bpsend.net/thread-377-1-1.html 通过cff , depends灯等软件可以看到dll,导出函数的信息,因为dll中本身就存了这些信息,存了dll中有哪些导 ...

  10. Kali Linux 从入门到实战:系统详解与工具指南

    Kali Linux 从入门到实战:系统详解与工具指南 1. Kali Linux 简介 Kali Linux 是一款基于 Debian 的 Linux 发行版,专为 渗透测试 和 网络安全审计 设计 ...