1.what is webflux?
Spring WebFlux is an asynchronous non-blocking WEB framework that can make full use of the hardware resources of multi-core CPUs to handle a large number of concurrent requests. Spring MVC is built on the Servlet API and uses a synchronous blocking I/O model. That is, each request corresponds to a thread for processing.
2.The differents WebFlux and Spring MVC
WebFlux:
- Asynchronous non-blocking: WebFlux is based on the reactive programming model, supports non-blocking I/O, can fully utilize multi-core CPU resources, and has better performance in high-concurrency scenarios because it does not allocate independent threads for each request. , thus avoiding the overhead caused by thread context switching.
- Reactive programming: WebFlux uses the Mono and Flux types provided by Project Reactor (or RxJava as an alternative) to represent asynchronous sequences of potentially zero, one, or more events, allowing developers to write asynchronous data processing logic.
- No Servlet API required: Although it can run on a Servlet container, it does not directly rely on the Servlet API and can run on non-blocking servers (such as Netty, Undertow, etc.).
- Functional programming style: In addition to providing an annotation programming model similar to Spring MVC, WebFlux also supports a functional programming model, allowing more flexible routing configuration through RouterFunction and other methods.
Spring MVC:
- Synchronous blocking: Spring MVC is based on the traditional Servlet API, and each HTTP request is usually bound to a separate thread until the request is processed and the response is sent.
- Threading model: By default, in Spring MVC applications, each request will create or obtain a thread from the thread pool, and release it back to the thread pool after processing is completed. This mode may affect the concurrency capability of the system when the request processing complexity is high or the thread pool size is limited.
- Depends on Servlet container: Spring MVC must be deployed and run in a container that supports Servlet API (such as Tomcat, Jetty, Undertow, Weblogic, etc.).
- API and programming model: Spring MVC mainly uses an annotation-driven approach to organize controllers and process request responses, such as through @Controller, @RequestMapping and other annotations.
performance
Being reactive and non-blocking doesn’t always make your application run faster, and building your code into a non-blocking execution mode itself comes with a small cost. However, in high-concurrency, low-computation, and I/O-intensive applications such as WEB applications, responsiveness and non-blocking can often be of value. Compared with the Servlet model used by SpringMVC, increasing the number of threads used by the Servlet container to process requests can alleviate this problem, but adding threads has a cost. By default, the JVM will allocate a thread stack of 1M when creating a new thread, so it is more More threads means more memory is needed; more threads will bring more thread context switching costs.
3.Code Project
experiment pupose:use webflux to write code
add dependency
<!-- WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
controller
method 1: springmvc annotation
package com.et.webflux;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@Slf4j
@RestController
@RequestMapping("/demo")
public class DemoController {
@Resource
private DemoService demoService;
@GetMapping("/monoTest")
public Mono<Object> monoTest() {
// method one
// String data = getOneResult("monoTest()");
// return Mono.just(data);
// method two
return Mono.create(cityMonoSink -> {
String data = demoService.getOneResult("monoTest()");
cityMonoSink.success(data);
});
}
@GetMapping("/fluxTest")
public Flux<Object> fluxTest() {
// method one
// List<String> list = getMultiResult("fluxTest()");
// return Flux.fromIterable(list);
// method two
return Flux.fromIterable(demoService.getMultiResult("fluxTest()"));
}
}
method 2: Java 8 Lambda functional programming
@Bean
public RouterFunction<ServerResponse> routes() {
// belove such as @RequestMapping
return RouterFunctions.route(POST("/addUser"), handler::addUser)
.andRoute(GET("/userList"), handler::userList)
.andRoute(GET("/findUserById/{id}"), handler::findUserById);
}
service
package com.et.webflux;
import java.util.List;
public interface DemoService {
String getOneResult(String methodName);
List<String> getMultiResult(String methodName);
User addUser(User user);
List<User> findAllUser();
User findUserById(Long id);
}
package com.et.webflux;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class DemoServiceImpl implements DemoService {
@Override
public String getOneResult(String methodName) {
return String.format("%s invoker success", methodName);
}
@Override
public List<String> getMultiResult(String methodName) {
List<String> list = new ArrayList<>(3);
for (int i = 0; i < 3; i++) {
list.add(String.format("%s invoker success, %d ", methodName, i + 1));
}
return list;
}
@Override
public User addUser(User user) {
user.setId(1L);
return user;
}
@Override
public List<User> findAllUser() {
List<User> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
int no = i + 1;
list.add(new User((long) no, "USER_" + no, "PWD_" + no, 18 + no));
}
return list;
}
@Override
public User findUserById(Long id) {
return new User(id, "USER_" + id, "PWD_" + id, 18);
}
}
above it just some key codes,for all codes ,you can see code reponsitory below.
Code Reponsible
4.Test
- start springboot application
- input http://localhost:8088/demo/fluxTest on the browser
- input http://localhost:8088/demo/monoTest on the browser