• Springboot 开发 Web Flux


    一、什么是响应式编程

      1.1 什么是WebFlux

            WebFlux是从Spring Framework5.0以后开始引入的响应式web编程框架。与传统的Spring mvc不同WebFlux不需要Servlet API,在完全异步且无阻塞的通过Reactor项目实现Reactive Streams 规范。

           WebFlux可以在有限资源下提高系统的吞吐量和伸缩性,这意味着在资源相同的情况下WebFlux可以处理更多的请求。

    1.2 MVC和WebFlux的比较

         (1) 工作方式:

           mvc的工作流程:主线程接收到请求(request)->  ..... -> 返回数据. 整个过程是单线程阻塞的,在处理好数据后才返回数据,如果用户请求比较多,那么吞吐量就比较低。

          (2)WebFlux:

           WebFlux的工作流程:主线程得到请求-> 立即返回数据与函数的组合(Mono或Flux) -> 开启一个新Work线程准备数据  ->  执行业务操作 --> Work线程工作完成 ---> 返回数据。

    spring mvc和 web flux的区别
    区别                       Spring mvcSpring WebFlux
    地址映射@Controller @RequestMapping 等

    Router Functions 提供函数式的API,用于创建Router Handler Filter

    数据流                Servlet APIReactive Streams: 一种支持背压的异步数据量标准。WebFlux默认使用的是Reactor。
    容器        Tomcat Jetty UndertowTomcat Jetty Netty Undertow

    IO 模型        

    同步的、阻塞的IO 异步非阻塞的IO
    吞吐量        
    数据库        Sql  NoSql支持NoSql,不支持Sql
    请求和响应        HttpServletRequest和HttpServletResponseServletResponse和ServletRequest
    业务处理性能 相同                相同

    2. 认识Mono和Flux

       2.1 什么是Mono和Flux

            Mono和Flux是Reactor中的两个基本概念。

           Mono和Flux都是事件发布者,为消费者提供订阅接口。当有事件发生时,Mono和Flux会回调消费者的相应方法,然后通知消费者相应的事件。这也是响应式编程模型。

          Mono和Flux用于处理异步数据流,它不是MVC中直接返回String或Object,而是将异步数据流包装成Mono或Flux对象。

    2.2 Mono和Flux的区别

         Flux可以发送多个item(例如:列表)。这些item可以经过若干算子(operators)后才被订阅。Mono只能发送一个item(例如:根据id查询)

        Mono 主要用于返回单个数据,Flux用于返回多个数据。

    二、开发WebFlux的流程:

      2.1 配置WebFlux依赖:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-webfluxartifactId>
    4. dependency>

    2.2 编写控制器:

    1. mport org.springframework.web.bind.annotation.GetMapping;
    2. import org.springframework.web.bind.annotation.RestController;
    3. import reactor.core.publisher.Mono;
    4. @RestController
    5. public class HelloController {
    6. @GetMapping("/")
    7. public Mono hello(){
    8. return Mono.just("Hello WebFlux Test dev!");
    9. }
    10. }

     2.3 添加mongo依赖并创建实体类:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-mongodb-reactiveartifactId>
    4. dependency>
    1. @Data
    2. @AllArgsConstructor
    3. @NoArgsConstructor
    4. @Document
    5. public class User {
    6. @Id
    7. private String id;
    8. private String name;
    9. private Integer age;
    10. }

    2.4 创建DAO

    1. import com.example.webfluxdemo.entity.User;
    2. import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
    3. public interface UserMongoDao extends ReactiveMongoRepository {
    4. }

    2.5 编写Handler:

    1. import org.springframework.http.MediaType;
    2. import org.springframework.stereotype.Component;
    3. import org.springframework.web.reactive.function.server.ServerRequest;
    4. import org.springframework.web.reactive.function.server.ServerResponse;
    5. import reactor.core.publisher.Mono;
    6. @Component
    7. public class HelloWorldHandler {
    8. public Mono sayHello(ServerRequest serverRequest){
    9. return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
    10. .body(Mono.just("This is WebFlux Demo!"),String.class);
    11. }
    12. }

    2.6 编写路由:

    1. @Configuration
    2. public class Router {
    3. @Resource
    4. private HelloWorldHandler helloWorldHandler;
    5. @Bean
    6. public RouterFunction getString(){
    7. return route(GET("/hello"),req->helloWorldHandler.sayHello(req));
    8. }
    9. }

    2.7 编写控制器:

    1. mport com.example.webfluxdemo.dao.UserMongoDao;
    2. import com.example.webfluxdemo.entity.User;
    3. import org.springframework.http.HttpStatus;
    4. import org.springframework.http.MediaType;
    5. import org.springframework.http.ResponseEntity;
    6. import org.springframework.web.bind.annotation.*;
    7. import reactor.core.publisher.Flux;
    8. import reactor.core.publisher.Mono;
    9. import javax.annotation.PostConstruct;
    10. import javax.annotation.Resource;
    11. import java.time.Duration;
    12. import java.util.HashMap;
    13. import java.util.Map;
    14. import java.util.stream.Collectors;
    15. @RestController
    16. @RequestMapping("/user")
    17. public class UserController {
    18. @Resource
    19. private UserMongoDao userMongoDao;
    20. @GetMapping(value ="/list")
    21. public Flux findAll(){
    22. return userMongoDao.findAll();
    23. }
    24. @PostMapping("")
    25. public Mono create( User user){
    26. return this.userMongoDao.save(user);
    27. }
    28. @GetMapping("/{id}")
    29. public Mono> getUserById(@PathVariable("id") String id){
    30. return this.userMongoDao.findById(id)
    31. .map(getUser -> ResponseEntity.ok(getUser))
    32. .defaultIfEmpty(ResponseEntity.notFound().build());
    33. }
    34. @DeleteMapping("/{id}")
    35. public Mono> delete(@PathVariable("id")String id){
    36. return userMongoDao.findById(id)
    37. .flatMap(existingUser ->
    38. userMongoDao.delete(existingUser)
    39. .then(Mono.just(new ResponseEntity(HttpStatus.OK)))
    40. )
    41. .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    42. }
    43. @PutMapping("/{id}")
    44. public Mono update(@PathVariable("id")String id,User user){
    45. return this.userMongoDao.findById(id)
    46. .flatMap(existingUser-> {
    47. existingUser.setName(user.getName());
    48. existingUser.setAge(user.getAge());
    49. return userMongoDao.save(user);
    50. })
    51. .map(update-> new ResponseEntity<>(update,HttpStatus.OK))
    52. .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    53. }
    54. @GetMapping(value ="/listdelay",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    55. public Flux getAll(){
    56. return userMongoDao.findAll().delayElements(Duration.ofSeconds(1));
    57. }
    58. }

     

     

  • 相关阅读:
    Sui主网升级至V1.10.1版本
    MD5算法
    Win11怎么修改关机界面颜色?Win11修改关机界面颜色的方法
    MultiButton按键驱动模块的使用
    SSM - Springboot - MyBatis-Plus 全栈体系(十四)
    数据库的数据类型
    华为云云耀云服务器L实例评测 | 实例评测使用之软件性能评测:华为云云耀云服务器下的 Redis 性能评测
    【Unity】AssetBundle加载与卸载
    构建高效且可伸缩的结果缓存
    Go 语言 设计模式-单例模式
  • 原文地址:https://blog.csdn.net/tonysong111073/article/details/127144426