1. 概述
Spring 5 包含 Spring WebFlux,它為 Web 應用程序提供反應式編程支持。
在本教程中,我們將使用反應式 Web 組件 RestController 和 WebClient 創建一個小型反應式 REST 應用程序。
我們還將探討如何使用 Spring Security 來安全地保護我們的反應式端點。
2. Spring WebFlux 框架
Spring WebFlux 內部使用 Project Reactor 以及其發佈者實現,包括 Flux 和 Mono。
該新框架支持兩種編程模型:
- 基於註解的反應式組件
- 功能式路由和處理
我們將重點關注基於註解的反應式組件,因為我們之前已經探索了功能式風格——路由和處理。
3. 依賴項
讓我們從 <em >spring-boot-starter-webflux</em> 依賴項開始,它會引入所有其他必需的依賴項:
- spring-boot 和 spring-boot-starter 用於基本 Spring Boot 應用程序設置
- spring-webflux 框架
- reactor-core,我們需要的用於響應式流,以及 reactor-netty
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.5.7</version>
</dependency>最新版本的 spring-boot-starter-webflux 可從 Maven Central 下載。
4. 反應式 REST 應用
現在我們將使用 Spring WebFlux 構建一個非常簡單的反應式 REST EmployeeManagement 應用。
- 使用簡單的領域模型——Employee,包含 id 和 name 字段
- 構建一個 REST API,使用 RestController 發佈 Employee 資源,既作為單個資源,也作為集合
- 使用 WebClient 構建客户端,以檢索相同的資源
- 使用 WebFlux 和 Spring Security 創建受保護的反應式端點
5. 反應式RestController
Spring WebFlux 支持與 Spring Web MVC 框架相同的基於註解的配置方式。
首先,在服務器端,我們創建一個帶有註解的控制器,該控制器發佈一個反應式流,該流包含 Employee 資源的流。
讓我們創建我們的帶有註解的 EmployeeController:
@RestController
@RequestMapping("/employees")
public class EmployeeController {
private final EmployeeRepository employeeRepository;
// constructor...
}EmployeeRepository 可以是任何支持非阻塞響應式流的數據存儲庫。
5.1. 單個資源
然後,讓我們在控制器中創建一個端點,該端點發佈一個單個 員工資源:
@GetMapping("/{id}")
public Mono<Employee> getEmployeeById(@PathVariable String id) {
return employeeRepository.findEmployeeById(id);
}我們用 Mono 包裹一個單個的 Employee 資源,因為我們最多返回一個員工。
5.2. 收集資源
我們還添加了一個端點,發佈所有 員工 的收集資源:
@GetMapping
public Flux<Employee> getAllEmployees() {
return employeeRepository.findAllEmployees();
}對於該集合資源,我們使用一種Flux類型的Employee,因為它是0.元素的發佈者。
6. 反應式 Web 客户端
WebClient,自 Spring 5 引入,是一個非阻塞客户端,並支持反應式流。
我們可以使用WebClient來創建客户端,以從EmployeeController提供的端點檢索數據。
讓我們創建一個簡單的EmployeeWebClient:
public class EmployeeWebClient {
WebClient client = WebClient.create("http://localhost:8080");
// ...
}我們使用其工廠方法 create 創建了一個 WebClient。它將指向 localhost:8080,這樣我們就可以使用該客户端實例發出的調用中定義的相對 URL。
6.1. 獲取單個資源
要從端點 /employee/{id}</em/> 獲取類型為 Mono</em/> 的單個資源,請執行以下操作:
Mono<Employee> employeeMono = client.get()
.uri("/employees/{id}", "1")
.retrieve()
.bodyToMono(Employee.class);
employeeMono.subscribe(System.out::println);6.2. 檢索集合資源
類似於從端點 employees/</em> 檢索類型為 Flux</em> 的集合資源。
Flux<Employee> employeeFlux = client.get()
.uri("/employees")
.retrieve()
.bodyToFlux(Employee.class);
employeeFlux.subscribe(System.out::println);我們還提供了一篇關於設置和使用 WebClient 的詳細文章。
7. Spring WebFlux 安全
我們可以使用 Spring Security 來保護我們的反應式端點。
假設我們有一個新的端點位於 EmployeeController 中。這個端點更新 Employee 的詳細信息並返回更新後的 Employee。
由於這允許用户修改現有員工,因此我們希望將此端點限制為 ADMIN 角色用户。
因此,讓我們為 EmployeeController 添加一個新方法:
@PostMapping("/update")
public Mono<Employee> updateEmployee(@RequestBody Employee employee) {
return employeeRepository.updateEmployee(employee);
}現在,為了限制對該方法的訪問,我們創建一個 SecurityConfig 並定義一些基於路徑的規則,只允許 ADMIN 用户訪問:
@EnableWebFluxSecurity
public class EmployeeWebSecurityConfig {
// ...
@Bean
public SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http) {
http.csrf().disable()
.authorizeExchange()
.pathMatchers(HttpMethod.POST, "/employees/update").hasRole("ADMIN")
.pathMatchers("/**").permitAll()
.and()
.httpBasic();
return http.build();
}
}此配置將限制對 /employees/update 端點的訪問。因此,只有具有 ADMIN 角色的用户才能訪問並更新現有 Employee。
此外,註解 @EnableWebFluxSecurity 增加了 Spring Security WebFlux 支持,幷包含一些默認配置。
欲瞭解更多信息,我們還提供了一篇關於配置和使用 Spring WebFlux 安全性的詳細文章。
8. 結論
本文介紹瞭如何創建和使用 Spring WebFlux 框架支持的反應式 Web 組件。作為示例,我們構建了一個小型反應式 REST 應用。
然後,我們學習瞭如何使用 <em >RestController</em > 和 `WebClient> 來發布和消費反應式流。
此外,我們還探討了如何使用 Spring Security 創建受保護的反應式端點。
除了反應式 <em >RestController</em > 和 <em >WebClient</em >>,Spring WebFlux 框架還支持反應式WebSocket> 以及相應的 `WebSocketClient>,用於反應式流的基於套接字的流式傳輸。
欲瞭解更多信息,我們還提供了一篇詳細的文章,重點介紹了與 Spring 5 中的反應式 WebSocket 一起工作。