当前位置:   article > 正文

Spring Boot集成webflux快速入门Demo

Spring Boot集成webflux快速入门Demo

1.webflux介绍

Spring WebFlux是一个异步非阻塞式的WEB框架,它能够充分利用多核CPU的硬件资源去处理大量的并发请求,而Spring MVC是构建于Servlet API之上,使用的是同步阻塞式I/O模型,即每一个请求对应一个线程去处理。

2.WebFlux 与 Spring MVC 区别

WebFlux:

  • 异步非阻塞: WebFlux 基于反应式编程模型,支持非阻塞 I/O,能够充分利用多核 CPU 资源,并且在高并发场景下具有更好的性能表现,因为 它不会为每个请求分配独立的线程,从而避免了线程上下文切换带来的开销。

  • 响应式编程: WebFlux 使用 Project Reactor(或者 RxJava 作为备选)提供的 Mono 和 Flux 类型来表示可能零个、一个或多个事件的异步序列,使得开发者可以编写异步数据处理逻辑。

  • 无需 Servlet API: 尽管可以在 Servlet 容器上运行,但它不直接依赖 Servlet API,能在非阻塞服务器(如 Netty、Undertow 等)上运行。

  • 函数式编程风格: 除了提供类似于 Spring MVC 的注解式编程模型外,WebFlux 还支持函数式编程模型,允许通过 RouterFunction 等方式进行更灵活的路由配置。

Spring MVC:

  • 同步阻塞: Spring MVC 基于传统的 Servlet API,每个 HTTP 请求通常都会绑定到一个单独的线程直到请求处理完成并发送响应为止。

  • 线程模型: 在默认情况下,Spring MVC 应用中,每个请求会创建或从线程池获取一个线程,处理完成后释放回线程池。这种模式在请求处理复杂度较高或线程池大小受限时,可能会影响系统的并发能力。

  • 依赖 Servlet 容器: Spring MVC 必须部署在支持 Servlet API 的容器中运行(如:Tomcat、Jetty、Undertow、Weblogic等)。

  • API 和编程模型: Spring MVC 主要采用注解驱动的方式组织控制器和处理请求响应,例如通过 @Controller、@RequestMapping 等注解。

性能

响应式和非阻塞并不是总能让应用跑的更快,况且将代码构建为非阻塞的执行方式本身还会带来少量的成本。但是在类似于WEB应用这样的高并发、少计算且I/O密集的应用中,响应式和非阻塞往往能够发挥出价值。 对比SpringMVC使用的Servlet模型,增加Servlet容器处理请求的线程数量可以缓解这一问题,但是增加线程是有成本的,JVM中默认情况下在创建新线程时会分配大小为1M的线程栈,所以更多的线程意味着需要更多的内存;更多的线程会带来更多的线程上下文切换成本。

3.代码工程

实验目的:使用webflux方式编写程序

添加依赖

  1. <!-- WebFlux -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-webflux</artifactId>
  5. </dependency>

编写controller

第一种 springmvc注解方式

  1. package com.et.webflux;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import reactor.core.publisher.Flux;
  7. import reactor.core.publisher.Mono;
  8. import javax.annotation.Resource;
  9. @Slf4j
  10. @RestController
  11. @RequestMapping("/demo")
  12. public class DemoController {
  13. @Resource
  14. private DemoService demoService;
  15. @GetMapping("/monoTest")
  16. public Mono<Object> monoTest() {
  17. // method one
  18. // String data = getOneResult("monoTest()");
  19. // return Mono.just(data);
  20. // method two
  21. return Mono.create(cityMonoSink -> {
  22. String data = demoService.getOneResult("monoTest()");
  23. cityMonoSink.success(data);
  24. });
  25. }
  26. @GetMapping("/fluxTest")
  27. public Flux<Object> fluxTest() {
  28. // method one
  29. // List<String> list = getMultiResult("fluxTest()");
  30. // return Flux.fromIterable(list);
  31. // method two
  32. return Flux.fromIterable(demoService.getMultiResult("fluxTest()"));
  33. }
  34. }

第二种 Java 8 Lambda函数式编程。

  1. @Bean
  2. public RouterFunction<ServerResponse> routes() {
  3. // 下面的操作相当于 @RequestMapping
  4. return RouterFunctions.route(POST("/addUser"), handler::addUser)
  5. .andRoute(GET("/userList"), handler::userList)
  6. .andRoute(GET("/findUserById/{id}"), handler::findUserById);
  7. }

service实现

  1. package com.et.webflux;
  2. import java.util.List;
  3. public interface DemoService {
  4. String getOneResult(String methodName);
  5. List<String> getMultiResult(String methodName);
  6. User addUser(User user);
  7. List<User> findAllUser();
  8. User findUserById(Long id);
  9. }
  1. package com.et.webflux;
  2. import org.springframework.stereotype.Service;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. @Service
  6. public class DemoServiceImpl implements DemoService {
  7. @Override
  8. public String getOneResult(String methodName) {
  9. return String.format("%s invoker success", methodName);
  10. }
  11. @Override
  12. public List<String> getMultiResult(String methodName) {
  13. List<String> list = new ArrayList<>(3);
  14. for (int i = 0; i < 3; i++) {
  15. list.add(String.format("%s invoker success, %d ", methodName, i + 1));
  16. }
  17. return list;
  18. }
  19. @Override
  20. public User addUser(User user) {
  21. user.setId(1L);
  22. return user;
  23. }
  24. @Override
  25. public List<User> findAllUser() {
  26. List<User> list = new ArrayList<>();
  27. for (int i = 0; i < 3; i++) {
  28. int no = i + 1;
  29. list.add(new User((long) no, "USER_" + no, "PWD_" + no, 18 + no));
  30. }
  31. return list;
  32. }
  33. @Override
  34. public User findUserById(Long id) {
  35. return new User(id, "USER_" + id, "PWD_" + id, 18);
  36. }
  37. }

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo

4.测试

  • 启动springboot工程

  • 访问地址http://localhost:8088/demo/fluxTest

  • 访问http://localhost:8088/demo/monoTest

5.引用

  • http://www.liuhaihua.cn/archives/710420.html

  • https://howtodoinjava.com/spring-webflux/spring-webflux-tutorial/

  • https://blog.csdn.net/qq_33204709/article/details/136908838

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/421850
推荐阅读
相关标签
  

闽ICP备14008679号