使用 WebFlux 进行异步处理
使用 Spring WebFlux 实现响应式编程,构建高并发且可扩展的 API。
使用 WebFlux 进行异步处理 是 CoddyKit 上的免费 Spring Boot 4 Microservices & REST APIs 课时。 这是第 2 节课,共 9 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Spring Boot 4 Microservices & REST APIs 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Spring Boot 4 Microservices & REST APIs 课程共包含 9 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Reactive? The Blocking Problem
In traditional applications, when your code needs to wait for something (like a database query or an external API call), it often blocks the current thread.
This means the thread can't do anything else until the operation completes. For many concurrent users, this can lead to:
- High resource consumption (many threads).
- Slower response times under heavy load.
- Limited scalability.
Introducing Spring WebFlux
Spring WebFlux is Spring's reactive web framework, built on Project Reactor. It allows you to build asynchronous, non-blocking applications.
Unlike Spring MVC, which uses a thread-per-request model, WebFlux uses an event-loop model. This means a few threads can handle many concurrent requests efficiently, making your API more scalable.
Core Concepts: Mono and Flux
At the heart of reactive programming in Spring WebFlux are two publishers from Project Reactor:
- Mono: Represents a stream that emits 0 or 1 item, then completes (or errors). Think of it like an optional future value.
- Flux: Represents a stream that emits 0 to N items, then completes (or errors). This is for collections or continuous streams of data.
They don't do anything until someone subscribes to them!
Your First Reactive Endpoint
Let's create a basic WebFlux controller. Notice we return a Mono<String> instead of a plain String. This tells Spring WebFlux to handle the response reactively.
Try running this example and access /hello in your browser.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@SpringBootApplication
@RestController
public class WebfluxApp {
public static void main(String[] args) {
SpringApplication.run(WebfluxApp.class, args);
}
@GetMapping("/hello")
public Mono<String> hello() {
return Mono.just("Hello, WebFlux!");
}
}Transforming Data with 'map'
Mono and Flux provide operators to transform data. The map() operator applies a synchronous function to each emitted item.
Here, we transform the "hello" string to uppercase. The original data is not changed, a new transformed value is emitted.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@SpringBootApplication
@RestController
public class WebfluxApp {
public static void main(String[] args) {
SpringApplication.run(WebfluxApp.class, args);
}
@GetMapping("/greet")
public Mono<String> greet() {
return Mono.just("hello")
.map(String::toUpperCase)
.map(s -> s + " WORLD!");
}
}Working with Collections using Flux
When you need to return a stream of multiple items, Flux is your go-to publisher. It can emit zero, one, or many items over time.
Here's an example returning a Flux<String> of fruits. When accessed, the browser will receive the items as a JSON array or a stream, depending on the client's Accept header.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@SpringBootApplication
@RestController
public class WebfluxApp {
public static void main(String[] args) {
SpringApplication.run(WebfluxApp.class, args);
}
@GetMapping("/fruits")
public Flux<String> getFruits() {
return Flux.just("Apple", "Banana", "Cherry", "Date");
}
}Practical Example: Reactive User Service
Let's combine what we've learned. Imagine a simple User data class. We can create a service that returns a Flux<User>, simulating fetching users from a database with a slight delay to demonstrate asynchronicity.
This endpoint will stream users as they become available, rather than waiting for all of them.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
@SpringBootApplication
@RestController
public class WebfluxApp {
public static void main(String[] args) {
SpringApplication.run(WebfluxApp.class, args);
}
record User(String id, String name) {}
@GetMapping("/users")
public Flux<User> getUsers() {
return Flux.just(
new User("1", "Alice"),
new User("2", "Bob"),
new User("3", "Charlie")
)
.delayElements(Duration.ofMillis(500)); // Simulate async delay
}
@GetMapping("/users/{id}")
public Mono<User> getUserById(String id) {
return Mono.just(new User(id, "User " + id))
.delayElement(Duration.ofSeconds(1));
}
}Graceful Error Handling
Reactive streams can fail. WebFlux provides operators like onErrorResume() or onErrorReturn() to handle errors gracefully, allowing you to provide a fallback value or another reactive sequence.
Without error handling, a failed stream would propagate the error to the subscriber, potentially causing an application crash or an undesirable HTTP 500 status.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@SpringBootApplication
@RestController
public class WebfluxApp {
public static void main(String[] args) {
SpringApplication.run(WebfluxApp.class, args);
}
@GetMapping("/fail")
public Mono<String> failingEndpoint() {
return Mono.error(new RuntimeException("Something went wrong!"))
.onErrorResume(e -> {
System.err.println("Error: " + e.getMessage());
return Mono.just("Fallback Message");
});
}
}Why WebFlux Boosts Scalability
By adopting WebFlux, your applications can achieve higher throughput and better resource utilization, especially for I/O-bound tasks. This is because:
- Fewer Threads: A small number of threads can manage a large number of concurrent connections.
- Non-Blocking: Threads are not idly waiting; they handle other requests while I/O operations complete.
- Efficient Resource Use: Leads to lower memory footprint and CPU usage under high load.
This makes WebFlux ideal for microservices that frequently interact with external systems.
Quick Check on Reactive Types
Consider the core reactive types we just learned.
Recap: Embracing Reactive with WebFlux
Great job! You've taken your first steps into asynchronous programming with Spring WebFlux.
- We learned how blocking I/O limits scalability.
- Spring WebFlux provides a non-blocking, reactive alternative.
- Mono handles 0-1 items, and Flux handles 0-N items.
- These publishers enable more efficient resource usage and higher concurrency.
Next, explore how to integrate WebFlux with reactive data repositories for end-to-end non-blocking applications!
常见问题解答
「使用 WebFlux 进行异步处理」课时是免费的吗?
是的 — 「使用 WebFlux 进行异步处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Spring Boot 4 Microservices & REST APIs 课程的其余内容,请升级到 CoddyKit PRO。 Spring Boot 4 Microservices & REST APIs 课程共包含 9 节课。
「使用 WebFlux 进行异步处理」这节课中我会学到什么?
使用 Spring WebFlux 实现响应式编程,构建高并发且可扩展的 API。 你通过在浏览器中直接运行的动手代码来练习 Spring Boot 4 Microservices & REST APIs,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Spring Boot 4 Microservices & REST APIs 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Spring Boot 4 Microservices & REST APIs 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 9 节。
「使用 WebFlux 进行异步处理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Spring Boot 4 Microservices & REST APIs 课中编写并运行代码吗?
能。每节 Spring Boot 4 Microservices & REST APIs 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。