Building reactive spring drivers from relational data

Let's talk about response

Reactive programming is a kind of programming paradigm for data flow and change propagation. To be frank, it is to propagate the changed value through data flow.

What is WebFlux

The name of the WebFlux module is spring webplus, and the Flux in the name comes from the class Flux in the Reactor. Spring webplus has a new non blocking functional Reactive Web framework, which can be used to build asynchronous, non blocking, event driven services, with excellent scalability.

Spring web plus module. The module includes support for responsive HTTP and WebSocket clients, and support for REST, HTML and WebSocket interaction programs. Generally speaking, Spring MVC is used for synchronous processing and Spring Webflux is used for asynchronous processing.

Spring Boot Webflux has two programming models, one is similar to Spring MVC annotation, the other is based on Reactor.

What is R2DBC?

Support for reactive relational database connection

theme

Experience spring boot 2.3.0.RC1, and expect MySQL reactive to show its head. Today, let's integrate springboot, R2DBC and mysql. Spring Data R2DBC is mainly used. Spring Data R2DBC applies familiar spring abstraction and repository support to R2DBC. It makes it easier to build spring driven applications in a responsive application stack that use relational data access technology.

POM

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.gitee.occo</groupId>
		<artifactId>occo-parent</artifactId>
		<version>2.0.0-SNAPSHOT</version>
	</parent>
	<artifactId>occo-sso</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-r2dbc</artifactId>
		</dependency>

		<dependency>
			<groupId>dev.miku</groupId>
			<artifactId>r2dbc-mysql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-release-plugin</artifactId>
				<configuration>
					<tagNameFormat>v@{project.version}</tagNameFormat>
					<autoVersionSubmodules>true</autoVersionSubmodules>
					<indentSize>4</indentSize>
					<useEditMode>true</useEditMode>
					<localCheckout>true</localCheckout>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Occo parent in POM can be replaced by

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.3.0.RC1</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>


<!--be unable to come down jar Add the following:-->
    <repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</pluginRepository>
	</pluginRepositories>

application.yml

server:
  port: 8000
  
spring:
  application:
    name: occo-sso
  r2dbc: 
    url: r2dbc:mysql://localhost:3306/occo
    username: root
    password: pwd2020
logging:
  level:
    org.springframework.data.r2dbc: DEBUG 

Implement a simple data operation

repository:

import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;

import com.gitee.occo.sso.user.entity.User;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Repository
public interface UserRepository extends ReactiveCrudRepository<User, Long>{

	@Query("SELECT * FROM user WHERE state = :state")
	Flux<User> findByState(Integer state);
	
	@Query("SELECT * FROM user WHERE username = :username")
	Mono<User> findByUsername(String username);
	
	@Query("SELECT * FROM user WHERE username LIKE :username")
	Flux<User> findByUsernameLike(String username);
}

service

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gitee.occo.sso.user.entity.User;
import com.gitee.occo.sso.user.repository.UserRepository;
import com.gitee.occo.sso.user.service.UserService;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserRepository userRepository;

	@Override
	public Mono<User> findById(Long id) {
		// TODO Auto-generated method stub
		return userRepository.findById(id);
	}

	@Override
	public Mono<User> findByUsername(String username) {
		// TODO Auto-generated method stub
		return userRepository.findByUsername(username);
	}

	@Override
	public Flux<User> findByUsernameLike(String username) {
		// TODO Auto-generated method stub
		return userRepository.findByUsernameLike(username);
	}

}

controller:

import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gitee.occo.sso.user.entity.User;
import com.gitee.occo.sso.user.service.UserService;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/user")
public class UserController {

	@Autowired
	UserService userService;
	
	@GetMapping("/findById/{id}")
	public Mono<User> getUserById(@PathVariable("id")Long id){
		return userService.findById(id);
	}
	
	@GetMapping("/findByUsername")
	public Mono<User> findByUsername(String username){
		return userService.findByUsername(username);
	}
	
	@GetMapping(value="/findByUsernameLike" ,produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
	public Flux<User> getByUsername(String username){
		return userService.findByUsernameLike(username+"%").delayElements(Duration.ofSeconds(2));
	}
}

PS: produces = mediatype. Application? Stream? JSON? Value should be added, otherwise it will wait for completion, and a request body will return.

Tags: Programming Spring Maven MySQL WebFlux

Posted on Wed, 13 May 2020 19:09:11 -0700 by phpcoder24july