Spring WebFlux Guide
Reactive Controller
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.*;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserRepository repo;
// Return Flux (0..N items)
@GetMapping
public Flux<User> listUsers() {
return repo.findAll();
}
// Return Mono (0..1 item)
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return repo.findById(id)
.switchIfEmpty(Mono.error(new NotFoundException()));
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<User> createUser(@RequestBody User user) {
return repo.save(user);
}
}
Reactor Operators
Flux<Integer> numbers = Flux.range(1, 10);
numbers
.filter(n -> n % 2 == 0) // [2,4,6,8,10]
.map(n -> n * n) // [4,16,36,64,100]
.take(3) // [4,16,36]
.flatMap(n -> fetchData(n)) // async mapping
.onErrorResume(e -> Flux.empty()) // error recovery
.subscribe(System.out::println);
// Combine streams
Flux.zip(stream1, stream2)
.map(tuple -> tuple.getT1() + tuple.getT2());
R2DBC Reactive Repository
// Dependencies
// spring-boot-starter-data-r2dbc
// r2dbc-postgresql (or r2dbc-h2 for testing)
public interface UserRepository extends ReactiveCrudRepository<User, Long> {
Flux<User> findByName(String name);
Mono<User> findByEmail(String email);
@Query("SELECT * FROM users WHERE active = :active")
Flux<User> findByActive(@Param("active") boolean active);
}