响应式编程生活案例:

传统形式:

一群人去餐厅吃饭,顾客1找服务员点餐,服务员把订单交给后台厨师,然后服务员等待,

当后台厨师做好饭,交给服务员,经过服务员再交给顾客1,依此类推,该服务员再招待顾客2。

服务员可以理解为服务器,服务器越多,可处理的顾客请求越多

响应式编程:

服务员记住到顾客1的要求,交给后台厨师,再记住顾客2的要求,交给后台厨师,依此类推

当厨师做好顾客1的饭,告知服务员,然后服务员把饭送到顾客1;

当厨师做好顾客2的饭,告知服务员,然后服务员把饭送到顾客2,依此类推

一系列的事件称为流,异步非阻塞,观察者的设计模式

代码案例:

传统:

int b=2;
int c=3
int a=b+c //a被赋值后,b和c的改变不会影响a
b=5;

响应式编程:

int b=2;
int c=3
int a=b+c 
b=5;//此时a变化为8,a会根据b、c的变化而变化

SpringBoot2.x的响应式编程基于Spring5;

而Spring5的响应式编程又基于Reactor和Netty、Spring WebFlux替代Spring MVC

响应式编程最大的核心是非阻塞,即后台的每一步每一段都要做到非阻塞

比如使用MySQL作为数据库,由于MySQL不提供响应式编程,所以会阻塞

因此响应式编程不应采用MySQL,应该使用非阻塞的NoSQL

Spring WebFlux有两种风格:基于功能和基于注解的。基于注解非常接近Spring MVC模型,如以下示例所示:

            @RestController
@RequestMapping(“/ users”)
public class MyRestController { @GetMapping(“/ {user}”)
public Mono <User> getUser( @PathVariable Long user){
// ...
} @GetMapping(“/ {user} / customers”)
public Flux <Customer> getUserCustomers( @PathVariable Long user){
// ...
} @DeleteMapping(“/ {user}”)
public Mono <User> deleteUser( @PathVariable Long user){
// ...
} }

第二种: 路由配置与请求的实际处理分开

            @Configuration
public class RoutingConfiguration { @Bean
public RouterFunction <ServerResponse> monoRouterFunction(UserHandler userHandler){
return route(GET( “/ {user}”).and(accept(APPLICATION_JSON)),userHandler :: getUser)
.andRoute(GET(“/ {user} / customers”).and(accept(APPLICATION_JSON)),userHandler :: getUserCustomers)
.andRoute(DELETE(“/ {user}”).and(accept(APPLICATION_JSON)),userHandler :: deleteUser);
} } @Component
public class UserHandler { public Mono <ServerResponse> getUser(ServerRequest request){
// ...
} public Mono <ServerResponse> getUserCustomers(ServerRequest request){
// ...
} public Mono <ServerResponse> deleteUser(ServerRequest request){
// ...
}
}

Spring WebFlux应用程序不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用src/main/webapp目录

可以整合多个模板引擎,除了REST外,您还可以使用Spring WebFlux提供动态HTML内容

Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker

简单的实战:

依赖

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

自动生成的SpringBoot项目还会有一个test依赖,可选

        <dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>

简单的Controller:

package org.dreamtech.webflux.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController
public class TestController {
@GetMapping("/test")
public Mono<String> test() {
return Mono.just("hello world");
}
}

访问http://localhost:8080/test,显示hello world说明成功

这里使用到了Mono,后边还会用到Flux,他们的实现很复杂,但可以简单地理解:

User、List<User>

1)简单业务而言:和其他普通对象差别不大,复杂请求业务,就可以提升性能
2)通俗理解:
Mono 表示的是包含 0 或者 1 个元素的异步序列
mono->单一对象 User
例如从redis根据用户ID查到唯一的用户,然后进行返回Mono<User>

Flux 表示的是包含 0 到 N 个元素的异步序列
flux->数组列表对象 List<User>
例如从redis根据条件:性别为男性的用户进行查找,然后返回Flux<User>
3)Flux 和 Mono 之间可以进行转换

进一步的使用

对User实体类实现增删改查功能:

package org.dreamtech.webflux.domain;

public class User {
private String id;
private String name; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public User(String id, String name) {
super();
this.id = id;
this.name = name;
} }

Service:

package org.dreamtech.webflux.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map; import org.dreamtech.webflux.domain.User;
import org.springframework.stereotype.Service; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; @Service
public class UserService {
// 使用Map模拟数据库
private static final Map<String, User> dataMap = new HashMap<String, User>();
static {
dataMap.put("1", new User("1", "admin"));
dataMap.put("2", new User("2", "John"));
dataMap.put("3", new User("3", "Rose"));
dataMap.put("4", new User("4", "James"));
dataMap.put("5", new User("5", "Bryant"));
} /**
* 返回数据库的所有用户信息
*
* @return
*/
public Flux<User> list() {
Collection<User> list = UserService.dataMap.values();
return Flux.fromIterable(list);
} /**
* 根据用户ID返回用户信息
*
* @param id 用户ID
* @return
*/
public Mono<User> getById(final String id) {
return Mono.justOrEmpty(UserService.dataMap.get(id));
} /**
* 根据用户ID删除用户
*
* @param id 用户ID
* @return
*/
public Mono<User> delete(final String id) {
return Mono.justOrEmpty(UserService.dataMap.remove(id));
}
}

Controller:

package org.dreamtech.webflux.controller;

import org.dreamtech.webflux.domain.User;
import org.dreamtech.webflux.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; @RestController
public class UserController {
private final UserService userService; public UserController(final UserService userService) {
this.userService = userService;
} /**
* 根据ID查找用户
*
* @param id 用户ID
* @return
*/
@GetMapping("/find")
public Mono<User> findById(final String id) {
return userService.getById(id);
} /**
* 获得用户列表
*
* @return
*/
@GetMapping("/list")
public Flux<User> list() {
return userService.list();
} /**
* 根据ID删除用户
*
* @param id 用户ID
* @return
*/
@GetMapping("/delete")
public Mono<User> delete(final String id) {
return userService.delete(id);
}
}

访问定义的三个API,发现和SpringMVC基本没有区别

所以,对返回进行延迟处理:

    @GetMapping("/list")
public Flux<User> list() {
return userService.list().delayElements(Duration.ofSeconds(3));
}

只是这些设置的话,等待3*list.size秒后全部返回,要突出流的特点,需要进行配置:

    @GetMapping(value = "/list", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<User> list() {
return userService.list().delayElements(Duration.ofSeconds(3));
}

这时候访问,可以发现每过3秒返回一个对象信息

使用WebClient客户端进行测试:

package org.dreamtech.webflux;

import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class WebClientTest {
@Test
public void test() {
Mono<String> bodyMono = WebClient.create().get().uri("http://localhost:8080/find?id=3")
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(String.class);
System.out.println(bodyMono.block());
}
}

SpringBoot 2.x (14):WebFlux响应式编程的更多相关文章

  1. SpringBoot使用WebFlux响应式编程操作数据库

    这一篇文章介绍SpringBoot使用WebFlux响应式编程操作MongoDb数据库. 前言 在之前一篇简单介绍了WebFlux响应式编程的操作,我们在来看一下下图,可以看到,在目前的Spring ...

  2. springboot2 webflux 响应式编程学习路径

    springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑问将会成为未来技术的趋势,是必学 ...

  3. [转]springboot2 webflux 响应式编程学习路径

    原文链接 spring官方文档 springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑 ...

  4. 07-Spring5 WebFlux响应式编程

    SpringWebFlux介绍 简介 SpringWebFlux是Spring5添加的新模块,用于Web开发,功能和SpringMvc类似的,WebFlux使用当前一种比较流行的响应式编程框架 使用传 ...

  5. springboot(二十三)Springboot2.X响应式编程

    序言 Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞,并 通过React ...

  6. SpringBoot实战派读书笔记---响应式编程

    1.什么是WebFlux? WebFlux不需要Servlet API,在完全异步且无阻塞,并通过Reactor项目实现了Reactor Streams规范. WebFlux可以在资源有限的情况下提高 ...

  7. Spring WebFlux 响应式编程学习笔记(一)

    各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了Spring WebFl ...

  8. 【SpringBoot】SpringBoot2.0响应式编程

    ========================15.高级篇幅之SpringBoot2.0响应式编程 ================================ 1.SprinBoot2.x响应 ...

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

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

随机推荐

  1. bzoj 4319: Suffix reconstruction 后缀数组+构造

    题目大意 给定后缀数组sa,要求构造出满足sa数组的字符串.或输出无解\(n\leq 5*10^5\) 题解 我们按照字典序来考虑每个后缀 对于\(Suffix(sa[i])\)和\(Suffix(s ...

  2. AtCoder Grand Contest 013 C:Ants on a Circle

    题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_c 题目翻译 给你一个周长为\(L\)的圆,有\(N\)只蚂蚁在圆上爬,速度为一单位距离每秒. ...

  3. poj2823Sliding Window——单调队列

    题目:http://poj.org/problem?id=2823 单调队列模板. 代码如下: #include<iostream> #include<cstdio> usin ...

  4. Windows WMIC命令使用详解1

    https://blog.csdn.net/enweitech/article/details/51982114 在CMD和Powershell中 使用WMIC 先决条件: a. 启动Windows ...

  5. 三层架构与MVC比较:

    三层架构与MVC比较: 1.两者不是同一概念 三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目. MVC是一个设计模式,它是根据项目的具体需求来决定是否适用于该项目. 那么架构跟设计模式 ...

  6. 算法java实现--回溯法--图的m着色问题

    (转自:http://blog.csdn.net/lican19911221/article/details/26264471) 图的m着色问题的Java实现(回溯法) 具体问题描述以及C/C++实现 ...

  7. HashMap为什么是线程不安全的

    HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点.对链表而言,新加入的节点会从头结点加入. 我们来分析一下多线 ...

  8. ASP.NET中 TextBox 文本输入框控件的使用方法

    TextBox控件又称文本框控件,为用户提供输入文本的功能. 1.属性 TextBox控件的常用属性及说明如表1所示. 表1 TextBox控件常用属性及说明 属性 说明 AutoPostBack 获 ...

  9. Javascript实现页面左边的菜单选中项高亮显示

    在项目开发过程中,遇到一个问题 在一个模板页面中,Layout.cshtml,页面左边放了一个菜单项menu,每一项都是一个链接到一个新的页面.但所有页面都是用这个模板Layout.cshtml.需要 ...

  10. Photoshop CC 智能切图功能介绍

    http://gdc.qq.com/ http://gdc.qq.com/?p=4445