springboot2.x簡單詳細教程--高階篇幅之響應式程式設計(第十五章)
阿新 • • 發佈:2018-11-24
一、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<User>
1)簡單業務而言:和其他普通物件差別不大,複雜請求業務,就可以提升效能
2)通俗理解:
Mono 表示的是包含 0 或者 1 個元素的非同步序列 (序列理解成流)
mono->單一物件 User redis->使用者ID-》唯一的使用者Mono<User>
Flux 表示的是包含 0 到 N 個元素的非同步序列
flux->陣列列表物件 List<User> redis->男性使用者->Flux<User>
Flux 和 Mono 之間可以進行轉換
3、Spring WebFlux有兩種風格:基於功能和基於註解的。基於註解非常接近Spring MVC模型,如以下示例所示:
第一種:
第二種:
“WebFlux.fn”是功能變體,它將路由配置與請求的實際處理分開,如以下示例所示:
@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) {
// ...
}
}
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
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itcast</groupId>
<artifactId>Springboot08_A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<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>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
官網說明
測試
1)
2)
3、啟動方式預設是Netty,8080埠
Netty:高效能網路框架,非同步非阻塞
4、參考:https://spring.io/blog/2016/04/19/understanding-reactive-types
5.模擬資料庫實現CRUD
1)service
package com.itcast.demo.service;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.itcast.demo.domain.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Service
public class UserService {
//模擬資料庫
private static final Map<String,User> map =new HashMap<>();
static{//一建立物件就初始化map
map.put("1", new User("1", "小王1"));
map.put("2", new User("2", "小王2"));
map.put("3", new User("3", "小王3"));
map.put("4", new User("4", "小王4"));
map.put("5", new User("5", "小王5"));
map.put("6", new User("6", "小王6"));
map.put("7", new User("7", "小王7"));
map.put("8", new User("8", "小王8"));
}
//返回所有資料
public Flux<User> list(){
Collection<User> list = UserService.map.values();
return Flux.fromIterable(list);
}
//通過id查出
public Mono<User> getById(final String id){
return Mono.justOrEmpty(UserService.map.get(id));
}
//通過id刪除使用者
public Mono<User> del(final String id){
return Mono.justOrEmpty(UserService.map.remove(id));
}
}
2)controller
package com.itcast.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.itcast.demo.domain.JsonData;
import com.itcast.demo.domain.User;
import com.itcast.demo.service.UserService;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @作者po
*/
@RestController
@RequestMapping("/api/v1")
public class UserController {
//@Autowired
//private UserService userService;
//通過構造的方式
private final UserService userService;
public UserController(final UserService userService ) {
this.userService=userService;
}
@GetMapping("test")
public Mono<String> Test01() {
return Mono.just("hello Mono");
}
@GetMapping("getById")
public Mono<User> getById(final String id){
return userService.getById(id);
}
@GetMapping("del")
public Mono<User> del(final String id){
return userService.del(id);
}
@GetMapping("list")
public Flux<User> list(){
return userService.list();
}
}
3)訪問
4)list
5)del
6)呼叫list的時候,希望拿到一個值就返回,如何體現這種效果
//import org.springframework.http.MediaType;
//拿到一個值就返回,即2s就返回,produces不配就沒有這樣的效果
@GetMapping(value="list",produces=MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<User> list(){//延遲兩秒
return userService.list().delayElements(Duration.ofSeconds(2));
}
應該:服務端的推送(像流水一樣)
四、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)在測試
package com.domain;
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 testBase(){
Mono<String> resp = WebClient.create()
.get()
//多個引數也可以直接放到map中,引數名與placeholder對應上即可
.uri("http://localhost:8080/api/v1/getById?id=1") //使用佔位符
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
System.out.println(resp.block());
}
@Test
public void testPlaceHolder(){
Mono<String> resp = WebClient.create()
.get()
.uri("http://localhost:8080/api/v1/getById?id={id}",1) //使用佔位符
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
System.out.println(resp.block());
}
}
2)先啟動主程式,再在方法上點JUnit Test