Before you know it, we have reached the 11th post in our WebFlux series. If you haven’t read the previous articles, remember to read them first, it will help you understand this article.

  1. Dig a big hole and WebFlux gets started!
  2. WebFlux pre-knowledge (1)
  3. WebFlux pre-knowledge (2)
  4. WebFlux pre-knowledge (3)
  5. WebFlux pre-knowledge (4)
  6. If you don’t understand asynchronous servlets, why WebFlux?
  7. At the beginning of WebFlux experience
  8. The server actively pushes data. What else can you think of besides WebSocket?
  9. What is the experience of writing a CURD in WebFlux?
  10. How does WebFlux request address routing work?

All right, let’s start today’s text.

We have already written a CURD in WebFlux, but MongoDB is used in the database. A lot of people are skeptical about WebFlux, including Songe’s earlier post, and others who said that WebFlux that can’t connect to MySQL doesn’t make any sense! This sentence is true, but we should also see that WebFlux is in a period of rapid development, all the impossible things will become possible, all the functions that did not have before will have later, WebFlux change speed is visible to the naked eye.

For example, the R2DBC we are going to introduce today can dispel some people’s doubts to some extent. Although the tool is not perfect, we have seen WebFlux working hard to solve these problems, and we have reason to believe that WebFlux will get better and better in the future.

Anyway, let’s get down to something practical.

1. What is R2DBC?

First of all, we should know that the most commonly used JDBC is actually synchronous, and the purpose of using WebFlux is to improve the response efficiency of the server side by means of asynchrony. Although WebFlux realizes asynchrony, JDBC is still synchronous, and most applications are inseparable from the database. So efficiency is essentially not improving.

So what can we do? Is there an asynchronous JDBC? There are!

There are two main types of asynchronous JDBC on the market:

  • ADAB: ADBA is an Oracle-led standard API for Java asynchronous database access that will be integrated into future Java standard releases. However, it has been slow to develop and only provides the OpenJDK sandbox features for developers to explore.
  • R2DBC: R2DBC is the official of Spring. After Spring5 released the responsive Web framework Spring WebFlux, it is in urgent need of database interaction API that can meet the requirements of asynchronous response. However, due to the lack of standards and drivers, The Pivotal team began its own research on Reactive Relational Database Connectivity, The R2DBC specification API is proposed to evaluate feasibility and discuss whether database vendors are interested in supporting responsive asynchronous non-blocking drivers. Originally there were only three database vendors, PostgreSQL, H2, and MSSQL, but now MySQL is joining in, which is a big plus. The latest version of R2DBC is 0.9.0.release.

It’s important to note that neither of these is a supplement to the original JDBC, and both are intended to redesign the database access scheme!

Now that you have a basic understanding of R2DBC, let’s go through a simple example to experience how to use R2DBC to operate a MySQL database.

2. Code practices

2.1 Create a Project

First let’s create a Spring Boot project and introduce WebFlux and R2DBC dependencies, as shown in the figure below:

After the project is successfully created, R2DBC dependencies are automatically added to the pom.xml file as follows:


Next we configure the database connection information in Note that this configuration is a little different from the previous one:


In addition to the key differences in the properties of the configuration file, the database connection protocol has changed from JDBC to R2DBC.

OK, so we are done with our preparations.

2.2 Database script

We prepare a simple data table as follows:

This script is very simple, I should not provide it.

2.3 CURD

Let’s start by providing an entity class like this:

public class User { @Id private Long id; private String username; private String address; // Omit getter/setter}

Then we need a UserRepository interface that inherits directly from ReactiveCrudRepository, which is similar to the previous MongoDB gameplay.

public interface UserRepository extends ReactiveCrudRepository<User,Long> {


Next we define the handler for the User table, which is similar to the one we used in MongoDB, as follows:

import static java.lang.Long.parseLong; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.web.reactive.function.server.ServerResponse.notFound; import static org.springframework.web.reactive.function.server.ServerResponse.ok; @Component public class UserHandler { @Autowired UserRepository userRepository; public Mono<ServerResponse> getAllUsers(ServerRequest serverRequest) { return ok().contentType(APPLICATION_JSON) .body(userRepository.findAll(), User.class); } public Mono<ServerResponse> addUser(ServerRequest serverRequest) { return ok().contentType(APPLICATION_JSON) .body(userRepository.saveAll(serverRequest.bodyToMono(User.class)), User.class); } public Mono<ServerResponse> deleteUser(ServerRequest serverRequest) { return userRepository.findById(parseLong(serverRequest.pathVariable("id"))) .flatMap(user -> userRepository.delete(user).then(ok().build())) .switchIfEmpty(notFound().build()); }}

Finally, we will configure the request address routing as follows:

@Configuration public class RouterConfiguration { @Bean RouterFunction<ServerResponse> userRouterFunction(UserHandler userHandler) { return RouterFunctions.nest(RequestPredicates.path("/user"), RouterFunctions.route(RequestPredicates.GET("/"), userHandler::getAllUsers) .andRoute(RequestPredicates.POST("/"), userHandler::addUser) .andRoute(RequestPredicates.DELETE("/{id}"), userHandler::deleteUser)); }}

There’s not much to talk about here, so if you’re confused, you can refer to our previous two articles.

  • What is the experience of writing a CURD in WebFlux? (a)
  • How does WebFlux request address routing work? (a)

3. The test

And finally, let’s just test it out.




If there is an ID and the ID already exists, the default is to update.


Delete successfully response 200:

Delete failed response 404:

This is a simple case of WebFlux operating on a relational database. For more on other uses of WebFlux, follow Songge to slowly dissection ~