51. Desenvolva Spring WebFlux baseado em anotações para gerar dados de contrapressão, ou seja, para enviar mensagens ao cliente o tempo todo

★ Dois métodos de desenvolvimento do Spring WebFlux

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

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

★ Desenvolva Spring WebFlux com base em anotações

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

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

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

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

O que é contrapressão:
Este é o conceito de Reativo.Quando a capacidade de consumo do assinante é muito inferior à do editor, o assinante (ou seja, o consumidor) possui um mecanismo para notificar o editor para cancelar ou encerrar a produção de dados. Isto O mecanismo pode ser chamado de "contrapressão".

Para ser franco, quando os consumidores têm um acúmulo de consumo, eles dizem ao produtor do impulso ao contrário que não preciso mais que você produza, por favor, diminua a velocidade. Isso é chamado de contrapressão.

Por exemplo, este método .onBackpressionDrop() é usado para habilitar a função de processamento de contrapressão para o método. O mecanismo é que quando o editor envia muitas mensagens ao assinante e o assinante não consegue lidar com elas, alguns dados serão descartados para garantir que o programa não travará.

Demonstração de código:

Use o spring webFlux para demonstrar uma função de contrapressão que o springmvc não pode executar, ou seja, o editor da mensagem pode enviar mensagens continuamente para os assinantes da mensagem. Continue enviando mensagens para o cliente.

Requisitos: Envie mensagens para o cliente a cada 5 segundos.

Ao criar o projeto, verifiquei anteriormente o Spring Web, que é baseado no Spring MVC, agora quero verificar o Spring Reactive Web, que é baseado na reatividade.
Insira a descrição da imagem aqui
Como mostrado na figura:
Pode-se ver que Spring WebFlux está integrado ao framework Reactor/baseado no framework Reactor.
Spring WebFlux e Reactor usam Netty como servidor Web por padrão.
Spring MVC usa Tomcat como servidor Web.
Insira a descrição da imagem aqui

Basta escrever um processo para consultar livros por ID. O banco de dados é substituído por uma coleção de mapas:
Insira a descrição da imagem aqui

Escreva um método para adicionar livros, tipo de envio postMapping, e teste-o com o postman.
Insira a descrição da imagem aqui
Escreva aqui os dados do objeto livro e envie-os no formato json.
O back-end usa o objeto modificado com a anotação @RequestBody para receber os dados.
public Book addBook(@RequestBody Book book){}
Insira a descrição da imagem aqui

A questão é que esse método reflete a contrapressão, que é continuar enviando dados ao cliente.

Torne o código mais simples:
Insira a descrição da imagem aqui

Algumas notas:
Insira a descrição da imagem aqui
Veja o código de todos os livros posteriormente.
Insira a descrição da imagem aqui

Implementação da função:

Requisitos: Envie mensagens para o cliente a cada 5 segundos.

Quando o projeto está em execução, insira um dado do livro, pode-se observar que a consulta é realmente executada a cada 5 segundos, e então os dados são enviados ao cliente.

Esta é a função de contrapressão que o Spring MVC não pode implementar.
Insira a descrição da imagem aqui

Se você alterar o projeto para spring mvc, o Flux não estará disponível.

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

Insira a descrição da imagem aqui

Código completo

dependências pom:

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

Insira a descrição da imagem aqui

domínio

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;
    }
}

Controlador de livro

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;
    }


}

Serviço de reservas

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;
    }
}

Função .onBackpressionDrop()

Check.onBackpressionDrop() A função deste método:

Insira a descrição da imagem aqui

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_44411039/article/details/132686709
Recomendado
Clasificación