一、SprinBoot2.x响应式编程简介
简介:讲解什么是reactive响应式编程和使用的好处
1、基础理解: 依赖于事件,事件驱动(Event-driven) 一系列事件称为“流” 异步 非阻塞
1)买奶茶的案例(一个一个等待处理)
2)响应式编程
观察者模式:服务员一直观察后台的情况,然后通知客户
网上的一个例子: int b= 2; int c=3 int a = b+c //命令式编程后续b和c变化,都不影响a b=5;
int b= 2; int c= 3 int a = b+c //响应式编程中,a的变化,会和b、c的变化而变化(事件驱动) b=5;
2、官网:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-webflux
SpingBoot2底层是用spring5,开始支持响应式编程,Spring又是基于Reactor试下响应式。
学习资料 1、reactive-streams学习资料:http://www.reactive-streams.org/ 2、web-flux相关资料:https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#spring-webflux
总结:响应式编程,必须每一个阶段都不阻塞,才能提升性能
二、SpringBoot2.x响应式编程webflux介绍
简介:讲解SpringBoot2.x响应式编程介绍 Mono、Flux对象和优缺点 1、Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架 与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞,并 通过Reactor项目实现Reactive Streams规范。 RxJava
2、Flux和Mono User List 1)简单业务而言:和其他普通对象差别不大,复杂请求业务,就可以提升性能 2)通俗理解: Mono 表示的是包含 0 或者 1 个元素的异步序列 (序列理解成流) mono->单一对象 User redis->用户ID-》唯一的用户Mono Flux 表示的是包含 0 到 N 个元素的异步序列 flux->数组列表对象 List redis->男性用户->Flux Flux 和 Mono 之间可以进行转换
3、Spring WebFlux有两种风格:基于功能和基于注解的。基于注解非常接近Spring MVC模型,如以下示例所示: 第一种: 第二种: “WebFlux.fn”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:
1 @Configuration
2 public class RoutingConfiguration {
3
4 @Bean
5 public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
6 return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
7 .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
8 .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
9 }
10
11 }
12
13 @Component
14 public class UserHandler {
15
16 public Mono<ServerResponse> getUser(ServerRequest request) {
17 // ...
18 }
19
20 public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
21 // ...
22 }
23
24 public Mono<ServerResponse> deleteUser(ServerRequest request) {
25 // ...
26 }
27 }
4、Spring WebFlux应用程序不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用src/main/webapp目录 5、可以整合多个模板引擎 除了REST Web服务外,您还可以使用Spring WebFlux提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker
三、SpringBoot2.x webflux实战
简介:webflux响应式编程实战 1、WebFlux中,请求和响应不再是WebMVC中的ServletRequest和ServletResponse,而是ServerRequest和ServerResponse
2、加入依赖,如果同时存在sprin g-boot-starter-web,则会优先用spring-boot-starter-web
1
2
3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6 <groupId>com.itcast</groupId>
7 <artifactId>Springboot08_A</artifactId>
8 <version>0.0.1-SNAPSHOT</version>
9 <parent>
10 <groupId>org.springframework.boot</groupId>
11 <artifactId>spring-boot-starter-parent</artifactId>
12 <version>2.0.1.RELEASE</version>
13 </parent>
14 <dependencies>
15 <!-- <dependency>
16 <groupId>org.springframework.boot</groupId>
17 <artifactId>spring-boot-starter-web</artifactId>
18 </dependency> -->
19 <dependency>
20 <groupId>org.springframework.boot</groupId>
21 <artifactId>spring-boot-starter-webflux</artifactId>
22 </dependency>
23 <dependency>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-test</artifactId>
26 <scope>test</scope>
27 </dependency>
28
29 </dependencies>
30 <build>
31 <plugins>
32 <plugin>
33 <groupId>org.springframework.boot</groupId>
34 <artifactId>spring-boot-maven-plugin</artifactId>
35 </plugin>
36 </plugins>
37 </build>
38
39 </project>
官网说明
测试
1)
2)
3、启动方式默认是Netty,8080端口
Netty:高性能网络框架,异步非阻塞
4、参考:https://spring.io/blog/2016/04/19/understanding-reactive-types
5.模拟数据库实现CRUD
1)service
1 package com.itcast.demo.service;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 import org.springframework.stereotype.Service;
8
9 import com.itcast.demo.domain.User;
10
11 import reactor.core.publisher.Flux;
12 import reactor.core.publisher.Mono;
13
14 @Service
15 public class UserService {
16
17 //模拟数据库
18 private static final Map<String,User> map =new HashMap<>();
19 static{//一创建对象就初始化map
20 map.put("1", new User("1", "小王1"));
21 map.put("2", new User("2", "小王2"));
22 map.put("3", new User("3", "小王3"));
23 map.put("4", new User("4", "小王4"));
24 map.put("5", new User("5", "小王5"));
25 map.put("6", new User("6", "小王6"));
26 map.put("7", new User("7", "小王7"));
27 map.put("8", new User("8", "小王8"));
28 }
29 //返回所有数据
30 public Flux<User> list(){
31 Collection<User> list = UserService.map.values();
32 return Flux.fromIterable(list);
33 }
34 //通过id查出
35 public Mono<User> getById(final String id){
36 return Mono.justOrEmpty(UserService.map.get(id));
37 }
38
39 //通过id删除用户
40 public Mono<User> del(final String id){
41 return Mono.justOrEmpty(UserService.map.remove(id));
42 }
43 }
2)controller
1 package com.itcast.demo.controller;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.beans.factory.annotation.Value;
5 import org.springframework.web.bind.annotation.GetMapping;
6 import org.springframework.web.bind.annotation.RequestMapping;
7 import org.springframework.web.bind.annotation.RestController;
8
9 import com.itcast.demo.domain.JsonData;
10 import com.itcast.demo.domain.User;
11 import com.itcast.demo.service.UserService;
12
13 import reactor.core.publisher.Flux;
14 import reactor.core.publisher.Mono;
15
16 /**
17 * @作者po
18 */
19 @RestController
20 @RequestMapping("/api/v1")
21 public class UserController {
22 //@Autowired
23 //private UserService userService;
24
25 //通过构造的方式
26 private final UserService userService;
27
28 public UserController(final UserService userService ) {
29 this.userService=userService;
30 }
31 @GetMapping("test")
32 public Mono<String> Test01() {
33 return Mono.just("hello Mono");
34 }
35
36 @GetMapping("getById")
37 public Mono<User> getById(final String id){
38 return userService.getById(id);
39 }
40 @GetMapping("del")
41 public Mono<User> del(final String id){
42 return userService.del(id);
43 }
44
45 @GetMapping("list")
46 public Flux<User> list(){
47 return userService.list();
48 }
49
50 }
3)访问
4)list
5)del
6)调用list的时候,希望拿到一个值就返回,如何体现这种效果
1 //import org.springframework.http.MediaType;
2 //拿到一个值就返回,即2s就返回,produces不配就没有这样的效果
3 @GetMapping(value="list",produces=MediaType.APPLICATION_STREAM_JSON_VALUE)
4 public Flux<User> list(){//延迟两秒
5 return userService.list().delayElements(Duration.ofSeconds(2));
6 }
应该:服务端的推送(像流水一样)
四、WebFlux客户端WebClient讲解
简介:讲解SpringBoot2.x WebFlux客户端WebClient的介绍和使用
1、反应式客户端
官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-webclient
实战
1)在测试
1 package com.domain;
2
3 import org.junit.Test;
4 import org.springframework.http.MediaType;
5 import org.springframework.web.reactive.function.client.WebClient;
6
7 import reactor.core.publisher.Mono;
8
9 public class WebClientTest {
10
11 @Test
12 public void testBase(){
13 Mono<String> resp = WebClient.create()
14 .get()
15 //多个参数也可以直接放到map中,参数名与placeholder对应上即可
16 .uri("http://localhost:8080/api/v1/getById?id=1") //使用占位符
17 .accept(MediaType.APPLICATION_JSON)
18 .retrieve()
19 .bodyToMono(String.class);
20 System.out.println(resp.block());
21
22 }
23
24 @Test
25 public void testPlaceHolder(){
26 Mono<String> resp = WebClient.create()
27 .get()
28 .uri("http://localhost:8080/api/v1/getById?id={id}",1) //使用占位符
29 .accept(MediaType.APPLICATION_JSON)
30 .retrieve()
31 .bodyToMono(String.class);
32 System.out.println(resp.block());
33
34 }
35
36 }
2)先启动主程序,再在方法上点JUnit Test