Introduction to the

Spring WebFlux is a new responsive Web Framework introduced in Spring Framework 5.0. Unlike Spring MVC, it does not require a Servlet API, is fully asynchronous and non-blocking, and implements the Reactive Streams specification through the Reactor project. Spring WebFlux is used to create completely asynchronous and non-blocking applications based on the event loop execution model.

【 Spring-webMVC + Servlet + Tomcat】 imperative, synchronous blocking 【 Spring-webflux + Reactor + Netty】 responsive, asynchronous non-blocking

Therefore, the database middleware usually used in WebFlux is different from the servlet+ Tomcat command and synchronous blocking commonly used in webFlux.

The database

In the daily development of the most used is to connect to the database, in the reactive, asynchronous blocking mode need to use a special component for R2DBC, easy to use. Add dependencies to Maven

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> The < version > 2.5.0 < / version > < / dependency > <! -- https://mvnrepository.com/artifact/com.github.jasync-sql/jasync-r2dbc-mysql --> <dependency> < the groupId > com. Making. Jasync - SQL < / groupId > < artifactId > jasync r2dbc - mysql < / artifactId > < version > 1.2.2 < / version > </dependency>Copy the code

Connect to mysql and import the responsive mysql derive with jasync, which is spring-boot-starter. Add the following configuration to the configuration file:

  r2dbc:
    url: mysql://%s:%[email protected]/database
    username: xxxx
    password: xxxxxxx
    pool:
      enabled: true
      initial-size: 100
      max-size: 200
      max-idle-time: 30m
      validation-query: SELECT 1
Copy the code

It is strange that autowire cannot automatically assemble database accounts and passwords, so manual injection is required

@Configuration public class MysqlConfig { @Value("${spring.r2dbc.url}") private String url; @Value("${spring.r2dbc.username}") private String username; @Value("${spring.r2dbc.password}") private String password; @Bean public R2dbcEntityTemplate r2dbcEntityTemplate(ConnectionFactory connectionFactory) { return new R2dbcEntityTemplate(connectionFactory); } @Bean public ConnectionFactory connectionFactory() { com.github.jasync.sql.db.Configuration configuration = URLParser.INSTANCE.parseOrDie(String.format(url, username, password), StandardCharsets.UTF_8); return new JasyncConnectionFactory(new MySQLConnectionFactory(configuration)); }}Copy the code

Pass in the database account and password from the URL. Then the link factory of the database is built through jasync’s factory. In other ways, R2DBC defines entity classes similar to traditional Spring-data-JPA:

@Data
@Builder
@Table("demo_user")
public class DemoUser {

    @Id
    private Long id;

    private String name;

    private Integer gender;

    private LocalDateTime updateTime;

    private LocalDateTime createTime;
}
Copy the code

Define the repository:

public interface DemoUserRepository extends ReactiveCrudRepository<DemoUser,Long> { <S extends T> Mono<S> save(S entity); /** * Saves all given entities. * * @param entities must not be {@literal null}. * @return {@link Flux} emitting the saved entities. * @throws IllegalArgumentException in case the given {@link Iterable entities} or one of its entities is  * {@literal null}. */ <S extends T> Flux<S> saveAll(Iterable<S> entities); /** * Saves all given entities. * * @param entityStream must not be {@literal null}. * @return {@link Flux} emitting the  saved entities. * @throws IllegalArgumentException in case the given {@link Publisher entityStream} is {@literal null}.  */ <S extends T> Flux<S> saveAll(Publisher<S> entityStream); }Copy the code

It directly inherits the ReactiveCrudRepository interface, which has defined some basic add, delete, change and query methods. The difference from traditional imperative programming is that the returned results are Mono or Flux wrapped, which are special in reactive programming. It should be noted that reository will take effect only after the following annotation is added

@EnableR2dbcRepositories(basePackages = "com.xxx.repository")
Copy the code

Then just use it like spring-data-jPA

private final DemoUserRepository userRepository;

    @GetMapping("/users")
    public Flux<AiFunction> getUser(){
        return userRepository.findAll();
    }
Copy the code

You can also customize SQL

@Query("select * from demo_user where name = :name")
Mono<AiFunction> findByUserName(String name);
Copy the code

To be continued…