51、基于注解方式开发Spring WebFlux,实现生成背压数据,就是实现一直向客户端发送消息

news2024/11/29 22:36:58

★ Spring WebFlux的两种开发方式

1. 采用类似于Spring MVC的注解的方式来开发。
   此时开发时感觉Spring MVC差异不大,但底层依然是反应式API。

2. 使用函数式编程来开发

★ 基于注解开发Spring WebFlux

开发上变化并不大,主要是处理方法的返回值可使用Mono或Flux,但并不强制使用Mono或Flux

WebFlux的变化主要是两点:
- 彻底抛弃Servlet API;
- 基于订阅-发布的异步机制。

这两点的区别主要体现在底层服务器能以较小的线程池处理更高的并发,从而提高应用的可伸缩性 

WebFlux支持基于背压(back press)的反应式流。

什么是背压:
这个是Reactive(反应) 的概念,当订阅者的消费能力,远低于发布者时,订阅者(也就是消费者)有通知取消或终止发布者生产数据的机制,这种机制可以称作为“背压”。

说白了就是:当消费者消费积压的时候,反向告诉推送生产者,我不需要你生产了,你慢点,这个叫背压。

比如这个.onBackpressureDrop() 方法,用来给方法开启背压处理功能,机制就是当发布者发送过多的消息给订阅者,订阅者处理不过来的时候,就会把一些数据丢掉,以保证程序不会崩溃。

代码演示:

用 spring webFlux 演示 springmvc 做不到的一个背压功能,就是消息的发布者可以不断的向消息的订阅者推送消息。就是一直向客户端发送消息。

需求:每隔5秒推送消息到客户端。

创建项目的时候,之前是勾选 Spring Web ,是基于Spring MVC 的,现在要勾选这个 Spring Reactive Web ,是基于反应式的。
在这里插入图片描述
如图:
可以看出 Spring WebFlux 是集成了 Reactor框架 / 基于Reactor框架
Spring WebFlux 和 Reactor 底层默认使用 Netty 作为Web服务器
Spring MVC 是使用 Tomcat 作为 Web 服务器
在这里插入图片描述

简单写一个通过id查询书本的流程,数据库用 Map 集合代替:
在这里插入图片描述

写一个添加书籍的方法,postMapping提交类型,用 postman测试
在这里插入图片描述
在这里写一个 书籍对象数据,用json格式提交,
后端用 @RequestBody 注解修饰的对象来接收数据。
public Book addBook(@RequestBody Book book){}
在这里插入图片描述

重点是这个方法,体现背压,就是一直向客户端发送数据

代码弄简洁点:
在这里插入图片描述

一些注释:
在这里插入图片描述
后面的查看所有书本的代码。
在这里插入图片描述

功能实现:

需求:每隔5秒推送消息到客户端。

在项目运行的时候 ,插入一条书本数据,可以看出的确是每5秒执行一次查询,然后向客户端推送数据。

这就是 spring mvc 无法实现的 背压功能。
在这里插入图片描述

如果把项目改成 spring mvc ,那么Flux 这个就不能用了。

    通过依赖把 <artifactId>spring-boot-starter-webflux</artifactId>
     改成  <artifactId>spring-boot-starter-web</artifactId>
     就是把 spring webflux 改成 spring mvc 框架

在这里插入图片描述

完整代码

pom依赖:

        <!-- 表明使用 WebFlux , 此时是反应式 Web 应用,默认使用 Reactor netty 作为服务器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

在这里插入图片描述

domain

package cn.ljh.my_annotation_flux.domain;
import lombok.Data;
@Data
public class Book
{
    private Integer id;
    private String name;
    private double price;
    private String author;
    
    public Book(Integer id, String name, double price, String author)
    {
        this.id = id;
        this.name = name;
        this.price = price;
        this.author = author;
    }
}

BookController

package cn.ljh.my_annotation_flux.controller;


import cn.ljh.my_annotation_flux.domain.Book;
import cn.ljh.my_annotation_flux.service.BookService;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.Collection;

@RestController
@RequestMapping("/books")
public class BookController
{
    private BookService bookService;
    //有参构造器完成依赖注入
    public BookController(BookService bookService)
    {
        this.bookService = bookService;
    }

    @GetMapping("/{id}")
    public Book viewBooks(@PathVariable Integer id)
    {
        Book book = bookService.getBook(id);
        return book;
    }



    //restful的方式提交请求 ,
    // @RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);
    @PostMapping("/addBook")
    public Book addBook(@RequestBody Book book)
    {
        bookService.addBook(book);
        return book;
    }

    //    开发基于 背压的 WebFlux 反应式流,来看 spring mvc 做不到的事
    //    WebFlux支持基于背压(back press)的反应式流。
    //    背压:很多种处理方式,消息的发布者可以不断的向消息的订阅者推送消息。消息过多后的一些处理方式。


        //这个获取图书的方法,使用到了背压的技术,相当于是一个数据流、消息发布者,会不断的向客户端生成数据,
        // 因此需要指定响应的数据类型: 数据是stream数据流,数据流里面的数据格式是json
    @GetMapping(value = "/viewBooks",produces = "application/stream+json")
    //需要直接用 Reactor 特性的时候,可以让处理方法返回 Mono 或 Flux
    public Flux<Book> viewBooks()
    {
        Flux<Collection<Book>> map =

                //周期性的向客户端推送数据,每隔5秒推送一次,  interval:间隔 , Duration:持续 ,  Seconds:秒
                //Flux.interval(Duration.ofSeconds(5)) 属于上游发送消息的发送者
                Flux.interval(Duration.ofSeconds(5))
                        //onBackpressureDrop作用:实现处理背压的功能
                        .onBackpressureDrop()
                        .map((i) -> bookService.getAllBooks());

        //将 Collection 转换 Flux (相当于把同步数据集 转换成 反应式的数据发布者)。
        //flatMapIterable 方法中的Lambda 表达式负责将 Coollection 中的元素转成 Flux 中的元素。
        Flux<Book> bookFlux = map.flatMapIterable(book -> book);

        return bookFlux;
    }


}

BookService

package cn.ljh.my_annotation_flux.service;


import cn.ljh.my_annotation_flux.domain.Book;
import java.util.Collection;

public interface BookService
{
    Book getBook(Integer id);

    Integer addBook(Book book);

    Collection<Book> getAllBooks();
}

BookServiceImpl

package cn.ljh.my_annotation_flux.service.impl;


import cn.ljh.my_annotation_flux.domain.Book;
import cn.ljh.my_annotation_flux.service.BookService;
import org.springframework.stereotype.Service;

import java.util.*;

//添加这个@Service注解,springboot就可以自动扫描这个Service组件的实现类,然后把这个类部署成容器中的bean。
@Service
public class BookServiceImpl implements BookService
{
    //添加一个 Map 集合,假设为数据库
    public static final Map<Integer, Book> bookDB = new LinkedHashMap<>();

    //创建一个自增id
    static int nextId = 4;

    //初始化这个数据库
    static
    {
        bookDB.put(1, new Book(1, "火影忍者", 100.0, "岸本"));
        bookDB.put(2, new Book(2, "家庭教师", 110.0, "天野明"));
        bookDB.put(3, new Book(3, "七龙珠Z", 120.0, "鸟山明"));
    }


    //查看图书
    @Override
    public Book getBook(Integer id)
    {
        Book book = bookDB.get(id);
        if (book == null){
            throw new RuntimeException("没有此图书信息!");
        }
        return book;
    }

    //添加图书
    @Override
    public Integer addBook(Book book)
    {
        book.setId(nextId);
        bookDB.put(nextId,book);
        //返回id,先返回在自增。
        return nextId++;
    }

    //查看所有的图书
    @Override
    public Collection<Book> getAllBooks()
    {
        //获取集合中的所有元素
        Collection<Book> values = bookDB.values();
        return values;
    }
}

.onBackpressureDrop() 作用

查 .onBackpressureDrop() 这个方法的作用:

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/991849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Devos勒索病毒:网络安全的新威胁,勒索病毒解密,数据恢复

随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显。近年来&#xff0c;一种名为Devos的勒索病毒在全球范围内肆虐&#xff0c;给企业和个人带来了极大的损失。本文将详细介绍Devos勒索病毒的特点、传播途径以及预防和应对措施&#xff0c;帮助大家更好地认识和防范这一…

针对JavaScript混淆加密,JShaman推出新功能

JShaman英文版在最新的一次更新时&#xff0c;增加了新功能&#xff1a; JavaScript代码混淆加密完成后&#xff0c;可以显示各功能耗时、处理的AST节点数量&#xff0c; 以此可知对代码做了哪些保护处理。 如上图所示&#xff0c;在此例中&#xff0c;对代码共进行了23项混淆…

Python标准数据类型-List(列表)

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;零基础入门篇 &#x1f4ac;个人格言&#xff1a;不断的翻越一座…

无涯教程-JavaScript - IMPRODUCT函数

描述 IMPRODUCT函数以x yi或x yj文本格式返回1到255个复数的乘积。两个复数的乘积为- $$(A BI)(C DI)(AC-BD)(A B)1 $$ 语法 IMPRODUCT (inumber1, [inumber2] ...)争论 Argument描述Required/OptionalInumber11 to 255 complex numbers to multiply.Required[inumbe…

xCode14.3.1运行MonkeyDev出现“Executable Not Found“的解决办法

安装MonkeyDev遇到的坑 环境&#xff1a;Xcode Version 14.3.1 (14E300c) 错误提示 is not a valid path to an executable file. 报错 /Users/xxxx//Library/Developer/Xcode/DerivedData/MonTest-ccparhdyzjuqhjdergwrngpfwwoh/Build/Products/Debug-iphoneos/MonTest.app…

基于大规模测量和多任务深度学习的电子鼻系统目标识别、浓度预测和状态判断

Target discrimination, concentration prediction, and status judgment of electronic nose system based on large-scale measurement and multi-task deep learning 摘要 为了实现响应特征的自动提取&#xff0c;简化模型的训练和应用过程&#xff0c;设计了一种双块知识…

python3网络爬虫--爬取B站视频弹幕(附源码)

文章目录 一&#xff0e;前言二&#xff0e;配置Protobuf 环境&生成编译文件1&#xff0e;配置Protobuf 环境2&#xff0e;生成编译文件 三&#xff0e;解析弹幕四&#xff0e;自动解析弹幕五&#xff0e;总结六&#xff0e;参考 本篇博文记录一下爬取B站弹幕的主要思路以及…

Pandas模块:Python科学计算神器之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…

SpotBugs检查java代码:不应该依赖平台默认编码(DM_DEFAULT_ENCODING)

https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html#internationalization-i18n 一个字节转换为字符串&#xff08;或字符串转化为字节&#xff09;的函数调用没有明确指明编码&#xff0c;而是依赖平台默认的编码&#xff0c;这可能导致应用在不同平台上的行为…

mac电脑做为开发机的一些初始化操作

Terminal设置 风格设置 修改Terminal提示符 /etc/zshrc 此处控制&#xff0c;大概70行左右 PS1"%n%m %1~ %# "目录颜色设置 编辑文件 vim ~/.bash_profile输入以下内容 export LS_OPTIONS--colorauto # 如果没有指定&#xff0c;则自动选择颜色 export CLICOLOR…

【C++漂流记】一文搞懂类与对象的封装

本篇文章主要说明了类与对象中封装的有关知识&#xff0c;包括属性和行为作为整体、访问权限、class与struct的区别、成员属性的私有化&#xff0c;希望这篇文章可以帮助你更好的了解类与对象这方面的知识。 文章目录 一、属性和行为作为整体二、访问权限三、class与struct的区…

spark集成hudi

启动spark-shell spark-shell \ > --jars /opt/software/hudi-spark3.1-bundle_2.12-0.12.0.jar \ > --conf spark.serializerorg.apache.spark.serializer.KryoSerializer\ > --conf spark.sql.extensionsorg.apache.spark.sql.hudi.HoodieSparkSessionExtension2…

腾讯云AI绘画:探究AI创意与技术的新边界

目录 一、2023的“网红词汇”——AI绘画二、智能文生图1、智能文生图的应用场景2、风格和配置的多样性3、输入一段话&#xff0c;腾讯云AI绘画给你生成一张图4、文本描述生成图像&#xff0c;惊艳全场 三、智能图生图&#xff1a;重新定义图像美学1、智能图生图的多元应用场景2…

Nginx 解析漏洞

文章目录 Nginx 解析漏洞1. 空字节漏洞1.1 漏洞描述1.2 漏洞复现1.3 修复方案 2. Nginx 解析漏洞复现2.1 漏洞描述2.2 漏洞复现2.3 获取GetShell2.4 修复方案 3. Nginx 文件名逻辑漏洞3.1 漏洞描述3.2 漏洞原理3.3 漏洞复现3.3.1 环境启动3.3.2 漏洞验证 3.4 漏洞利用3.5 修复方…

X(推特)“鸡贼”手段曝光:这些广告并没有标注,你知道吗?

在使用推特的时候&#xff0c;有些人可能会注意到&#xff0c;一些广告并没有正确地标注&#xff0c;看起来很像普通的内容&#xff0c;十分难以区分。美国的联邦贸易委员会&#xff08;FTC&#xff09;和欧盟的欧洲广告标准局&#xff08;EASA&#xff09;等机构都对广告标签有…

WhatsApp的两个商业模式该如何选择

WhatsApp Business 是什么 目前 WhatsApp 提供两种商业模式&#xff0c;企业应根据自身需求选择相应版本。 第一个版本是 WhatsApp Business&#xff1a;初创企业只需一个手机应用程序&#xff0c;便可以个体单位与客户轻松互动; 另一个版本是 WhatsApp Business API&#xff…

如何优雅地实现接口防刷

背景 最近在学习redis&#xff0c;想到了之前的写的一个案例demo&#xff0c;实现了接口的流量防刷。主要是为了防止爬虫爬取接口&#xff0c;当然可以适用于那些需要进行流控的系统&#xff0c;shigen画了一张草图展示主要的原理和过程&#xff1a; 首先用户请求系统的接口&a…

一篇文章教会你如何降低代码的冗余度——探索指针数组,数组指针,函数指针,函数指针数组,回调函数的奥妙

前言&#xff1a;人们总说指针是c语言的灵魂&#xff0c;是因为指针的使用技巧是“千姿百态”的&#xff0c;程序员可以通过指针来直接访问内存&#xff0c;这就赋予了它功能的多样性以及更多意想不到的编程技巧与方式&#xff0c;在本篇文章中&#xff0c;笔者就给大家带来指针…

同时安装python2和3解决方案

我先安装python3后&#xff0c;按照网上步骤&#xff0c;继续安装好python2&#xff0c;直接运行python -v只能显示python2&#xff0c;运行python3找不到此命令&#xff0c;通过https://blog.csdn.net/qq_64409509/article/details/131514944这篇文章找到了解决方案&#xff0…

MindFusion.Diagramming for ASP.NET MVC 4.2 Crack

ASP.NET MVC 4.2 的 MindFusion.Diagramming 添加对多个图表页面和选项卡式图表视图的支持。 2023 年 9 月 8 日 - 16:57新版本 特征 多个图表页面-添加了DiagramDocument 类&#xff0c;它表示图表页面或工作表的集合。 可以将新页面添加到文档中&#xff0c;并且可以删除或重…