Today we are going to learn about WebFlux. Why do you want to learn WebFlux all of a sudden?
Because I wanted to learn the Spring Cloud Gateway and found it was based on Technologies like Spring5.0+SpringBoot2.0+WebFlux. That’s why it’s important to take a quick look at WebFlux technology.
When IT came time to learn WebFlux, I found that I needed functional programming in Java 8, Stream streaming and other technologies as pre-knowledge. They go together like nesting dolls.
So there are two more articles to learn: lambda expressions and Java 8 streams.
I just want to learn the Spring Cloud Gateway, as a pre-knowledge, I do not plan to deeply study WebFlux for the time being, just a simple study.
With that said, let’s begin today’s lesson.
What is a WebFlux
The original Web Framework included in the Spring Framework, Spring Web MVC, was built specifically for the Servlet API and Servlet container. Spring WebFlux, the reactive stack Web framework, was added late in version 5.0. It is completely non-blocking, supports Reactive Stream backpressure, and runs on servers such as Netty, Undertow, and Servlet 3.1 + containers.
The above text and pictures are from the official website. From this we can roughly know that Spring WebFlux is benchmarking Spring MVC.
Spring WebFlux is an asynchronous non-blocking IO model that supports a large number of concurrent accesses with a small number of container threads. The underlying use of Netty containers also differs from traditional SpringMVC, which is servlet-based.
The response time of the interface will not be shortened due to the use of WebFlux, and the processing results of the server still have to be processed by the worker thread and then returned to the front end.
Reactive library
1. Reactive Stream
Reactive Stream is one of the terms you should notice. What does that mean?
Let’s start by looking at Reactive Programming, Microsoft’s approach to asynchronous Programming for server-side Programming in high-concurrency environments.
Reactive Stream is the specification for Reactive programming, and on the Java platform, Developed by Netflix (RxJava), TypeSafe (Scala, Akka), Pivatol (Spring, Reactor).
It consists of the following components:
- Publisher: Publishes elements to subscribers
- Subscriber: Consumption element
- Subscribe: In a publisher, when a subscription is created, it is shared with the subscriber
- Processor: Data is processed between publishers and subscribers
2. Reactor
Reactive Stream is a Reactive programming specification, but as an application API, applications will definitely need a higher-level, richer API to write asynchronous logic. That’s the role of the reaction library.
The Reactor framework is implemented by Pivotal based on Reactive Programming. It complies with the Reactive Streams specification. It provides Mono and Flux API types that handle 0.. 1 () and 0.. Data sequence of N (). Is a completely non-blocking, responsive programming framework for the JVM with efficient requirements management that handles “backpressure” well. Reactor is the preferred reaction library for Spring WebFlux.
From the above concepts, the most important thing to remember is Flux and Mono, the Reactor’s core classes:
- Mono: Implements Publisher and returns 0 or 1 element.
- Flux: Implements Publisher and returns N elements.
Both are publishers.
3. Reactive Stream, Reactor and WebFlux
Reactive Stream (Reactive Stream), Reactor (Reactor) and WebFlux (Reactive Stream)
Reactive Stream
It’s a set of reactive programmingstandard 和 specification;Reactor
Is based onReactive Streams
A set ofReactive programming framework;WebFlux
以Reactor
Based on the implementationWeb
In the field ofReactive programming framework.
Initial code experience
With all the concepts mentioned above, it’s finally time for the code section, so let’s briefly experience what the code looks like.
To create a Spring Boot project (Reactive Web), you need to build a Spring Boot project (Reactive Web). You need to build a Spring Boot project (Reactive Web).
1. Mono
@RestController
public class HelloController {
@GetMapping("/hello")
public Mono<String> hello(a) {
long start = System.currentTimeMillis();
Mono<String> hello = Mono.fromSupplier(() -> getHelloStr());
System.out.println(Interface Time: + (System.currentTimeMillis() - start));
return hello;
}
private String getHelloStr(a) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello"; }}Copy the code
To start the project, the browser accesses the /hello interface and the console outputs the following:
Interface time: 0
As you can see, in the WebFlux interface, requests are not blocked, so the interface time on the server side is 0.
2. Flux
@GetMapping(value = "/flux",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> flux(a) {
Flux<String> flux = Flux.fromArray(new String[]{"Black"."Xiao pang".Small six ""."Xin"}).map(s -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Class two:" + s;
});
return flux;
}
Copy the code
The browser is as follows:
Flux is also a Publisher and can be produced by an array. Note that the content-type returned here is MediaType.TEXT_EVENT_STREAM_VALUE, text/event-stream.
Text /event-stream is a way for the server to push messages to the browser, which is a bit different from the WebSocket we are familiar with. I’m not going to write that for now.
Operating database
Spring Boot 2.3.0.release has officially supported the R2DBC based MySQL driver.
R2DBC: R2DBC is the Spring official in Spring5 released a responsive Web framework Spring WebFlux after the urgent need to meet the asynchronous response of the database interaction API, but 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 the feasibility and discuss whether database vendors are interested in supporting responsive asynchronous non-blocking drivers. PostgreSQL, H2, and MSSQL were the first three vendors, but now MySQL has joined the fray.
Today we will learn how to operate MySQL database based on R2DBC.
1. Create projects
Select these dependencies and create a new project:
The pom.xml file looks like this:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</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>
</dependencies>
Copy the code
And then the application. The properties:
server.port=8081
spring.r2dbc.url=r2dbcs:mysql://locahost:3306/test
spring.r2dbc.username=root
spring.r2dbc.password=root
Copy the code
2. Create a database table
CREATE TABLE `test_user` (
`user_id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(255),
`age` int,
`address` varchar(255),PRIMARY KEY (`user_id`) USING BTREE
)
Copy the code
Create a simple test_user table.
3. Create related classes
Entity class
@Table("test_user")
public class User {
@Id
private int userId;
private String userName;
private int age;
private String address;
// omit the getter and setter
}
Copy the code
UserRepository, which is the DAO equivalent
public interface UserRepository extends ReactiveCrudRepository<User.Integer> {}Copy the code
UserController controller
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserRepository userRepository;
@RequestMapping("/getAllUser")
public Flux<User> getAllUser(a) {
Flux<User> userFlux = userRepository.findAll();
return userFlux;
}
@RequestMapping("/addUser")
public Mono<User> addUser(User user) {
Mono<User> mono = userRepository.save(user);
returnmono; }}Copy the code
With that done, it’s time to launch the project and test it out.
4. Start the test
After the project started, we tested it with Postman.
Request address routing
We still use the database table and entity classes from the previous step, but instead of UserController, we use UserHandler and RouterConfiguration.
createUserhandler.java
@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(Integer.valueOf(serverRequest.pathVariable("userId"))) .flatMap(user -> userRepository.delete(user).then(ok().build())) .switchIfEmpty(notFound().build()); }}Copy the code
createRouterConfiguration
@Configuration
public class RouterConfiguration {
@Bean
RouterFunction<ServerResponse> userRouterFunction(UserHandler userHandler) {
return RouterFunctions.nest(RequestPredicates.path("/user"),
RouterFunctions.route(RequestPredicates.GET("/getAllUser"), userHandler::getAllUsers)
.andRoute(RequestPredicates.POST("/addUser"), userHandler::addUser)
.andRoute(RequestPredicates.DELETE("/{userId}"), userHandler::deleteUser)); }}Copy the code
- This configuration class does something like this
SpringMVC
In theDispatcherServlet
, responsible for the distribution of requests, according to different request URLS, find the corresponding processor to process. - through
RouterFunctions
Such a utility class to createRouterFunction
Instance. - The nest method is called first, and the first parameter is set as a prefix to the address to be configured, similar to what we wrote directly on the Controller class
@RequestMapping
Annotation to configure the address. nest
The second argument to the method isRouterFunction
Examples, every one of themRouterFunction
Instance byRouterFunctions.route
Method, the first parameter is the requested URL (note that the address is configured with a common prefix), and the second parameter is configured with a method referenceHandlerFunction
This is the handler of the current request.- through
addRoute
Method to configure multiple routing policies.
test
Modification:
The query is the same as before:
applicability
The website advises:
-
There is no need to migrate if you are using SpringMVC well. Imperative programming is the easiest way to write, understand, and debug code. Because the libraries and code of the old project were based on blocking.
-
If your team is going to use a non-blocking Web framework, WebFlux is certainly a technical route to consider, and it supports programming patterns in a way that is analogous to SpringMvc’s annotations. It is also possible to have WebMvc share controllers with WebFlux in a microservice architecture. The cost of switching is fairly small.
-
If you need to call a remote service in a SpringMVC project, you can consider using WebClient, and the return value of the method can be considered Reactive Type. The longer the latency of each call or the higher the interdependence of the calls, the greater the benefit.
-
In the microservices architecture, you can mix applications that use either Spring MVC or Spring WebFlux controller or Spring WebFlux functional endpoints. Supporting the same annotation-based programming model in both frameworks makes it easier to reuse knowledge while choosing the right tool for the right job.
Spring WebFlux is not about making your application run faster (compared to SpringMVC), it’s about scaling your system with limited resources, so it’s worth considering if you’re comfortable with responsive programming and applying it to your new system, otherwise stick with WebMVC.
conclusion
Learn here, more or less also have some understanding, but there are a lot of things to learn behind. Ok, so far I have added a lot of things, but it is still not perfect, I will add it later when I have time.
Article Reference:
Spring Reactor Programming (Juejin)
Initial experience of WebFlux (QQ.com)