最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring-webflux?響應(yīng)式編程的實(shí)例詳解

 更新時(shí)間:2022年09月05日 14:59:12   作者:魚找水需要時(shí)間  
Spring 提供了兩個(gè)并行堆棧,一種是基于帶有 Spring MVC 和 Spring Data 結(jié)構(gòu)的 Servlet API,另一個(gè)是完全反應(yīng)式堆棧,它利用了 Spring WebFlux 和 Spring Data 的反應(yīng)式存儲(chǔ)庫,這篇文章主要介紹了Spring-webflux?響應(yīng)式編程,需要的朋友可以參考下

1. 前言

Spring 提供了兩個(gè)并行堆棧。一種是基于帶有 Spring MVC 和 Spring Data 結(jié)構(gòu)的 Servlet API。另一個(gè)是完全反應(yīng)式堆棧,它利用了 Spring WebFlux 和 Spring Data 的反應(yīng)式存儲(chǔ)庫。在這兩種情況下,Spring Security 都提供了對(duì)兩種堆棧的支持。

反應(yīng)式宣言

2. Spring-webflux簡(jiǎn)介

Spring WebFlux 是在 5.0 版中添加的。它是完全無阻塞的,支持 Reactive Streams背壓,并且可以在 Netty、Undertow 和 Servlet 3.1+ 容器等服務(wù)器上運(yùn)行。

Spring-webflux官網(wǎng)

3. 什么是“響應(yīng)式”

所謂響應(yīng)式,舉個(gè)例子,當(dāng)調(diào)用一個(gè)api獲取數(shù)據(jù)時(shí),無需阻塞等待數(shù)據(jù)返回,而是當(dāng)有數(shù)據(jù)返回時(shí)會(huì)進(jìn)行告知??梢婍憫?yīng)式是非阻塞的,意味著調(diào)用方法后,CPU可以去做別的事情,當(dāng)接收到數(shù)據(jù)響應(yīng)時(shí)CPU再回來處理,這種方式提高了系統(tǒng)的吞吐量。

而響應(yīng)式編程,其實(shí)是為這種異步非阻塞的流式編程制定的一套標(biāo)準(zhǔn)。流式編程已不陌生了,Java8提供的stream api就是這種風(fēng)格。這套標(biāo)準(zhǔn)包括對(duì)運(yùn)行環(huán)境(JVM、JavaScript)以及網(wǎng)絡(luò)協(xié)議相關(guān)的規(guī)范。

和傳統(tǒng)的阻塞式servlet容器不一樣。響應(yīng)式容器能進(jìn)一步提高資源的利用率,避免線程長(zhǎng)時(shí)間處于等待狀態(tài),能以較少的線程處理更多的請(qǐng)求,缺點(diǎn)是整個(gè)處理鏈路必須是異步的,是基于事件響應(yīng)的,不能阻塞事件線程,不然服務(wù)器性能會(huì)急劇下降,當(dāng)然spring webflux并不能完整的替代傳統(tǒng)的阻塞式容器,可根據(jù)需求進(jìn)行選型。

應(yīng)用案例Geteway

所有微服務(wù)的請(qǐng)求都會(huì)通過網(wǎng)關(guān),如果采用mvc 對(duì)于并發(fā)量有一定的瓶頸。

4. Spring-webflux的響應(yīng)式API

Spring-webflux框架是基于Reactor這個(gè)開源項(xiàng)目開發(fā)的。Reactor框架是跟Spring緊密配合的。

里邊提供了兩種API類型,分別是MonoFlux;

  • Mono表示0 或 1個(gè)元素,
  • Flux表示0 至 N個(gè)元素,

5. Spring MVC 還是 WebFlux?

這兩個(gè)web框架分別代表著兩種不同類型的編程流派,官方給出了一個(gè)圖作為對(duì)比如下

建議考慮以下具體點(diǎn):

  • 如果您有一個(gè)運(yùn)行良好的 Spring MVC 應(yīng)用程序,則無需更改。命令式編程是編寫、理解和調(diào)試代碼的最簡(jiǎn)單方法。您可以選擇最多的庫,因?yàn)?strong>從歷史上看,大多數(shù)都是阻塞的。
  • Spring WebFlux 提供與該領(lǐng)域中其他人相同的執(zhí)行模型優(yōu)勢(shì),并且還提供服務(wù)器選擇(Netty、Tomcat、Jetty、Undertow 和 Servlet 3.1+ 容器)、編程模型(帶注釋的控制器和功能性 Web 端點(diǎn))的選擇,以及反應(yīng)庫(Reactor、RxJava 或其他)的選擇。
  • 如果您對(duì)用于 Java 8 lambda 或 Kotlin 的輕量級(jí)、功能性 Web 框架感興趣,您可以使用 Spring WebFlux 功能性 Web 端點(diǎn)。對(duì)于要求不那么復(fù)雜的小型應(yīng)用程序或微服務(wù)來說,這也是一個(gè)不錯(cuò)的選擇,它們可以從更高的透明度和控制中受益。
  • 在微服務(wù)架構(gòu)中,您可以混合使用帶有 Spring MVC 或 Spring WebFlux 控制器或帶有 Spring WebFlux 功能端點(diǎn)的應(yīng)用程序。在兩個(gè)框架中都支持相同的基于注釋的編程模型,可以更輕松地重用知識(shí),同時(shí)為正確的工作選擇正確的工具。
  • 評(píng)估應(yīng)用程序的一種簡(jiǎn)單方法是檢查其依賴關(guān)系。如果您要使用阻塞持久性 API(JPA、JDBC)或網(wǎng)絡(luò) API,那么 Spring MVC 至少是常見架構(gòu)的最佳選擇。Reactor 和 RxJava 在單獨(dú)的線程上執(zhí)行阻塞調(diào)用在技術(shù)上是可行的,但您不會(huì)充分利用非阻塞 Web 堆棧。
  • 如果您有一個(gè)調(diào)用遠(yuǎn)程服務(wù)的 Spring MVC 應(yīng)用程序,請(qǐng)嘗試響應(yīng)式WebClient. 您可以直接從 Spring MVC 控制器方法返回反應(yīng)類型(Reactor、RxJava或其他)。每個(gè)呼叫的延遲或呼叫之間的相互依賴性越大,好處就越顯著。Spring MVC 控制器也可以調(diào)用其他響應(yīng)式組件。
  • 如果您有一個(gè)大型團(tuán)隊(duì),請(qǐng)記住向非阻塞、函數(shù)式和聲明式編程轉(zhuǎn)變的陡峭學(xué)習(xí)曲線。在沒有完全開關(guān)的情況下啟動(dòng)的一種實(shí)用方法是使用 reactive WebClient。除此之外,從小處著手并衡量收益。我們預(yù)計(jì),對(duì)于廣泛的應(yīng)用,這種轉(zhuǎn)變是不必要的。如果您不確定要尋找什么好處,請(qǐng)先了解非阻塞 I/O 的工作原理(例如,單線程 Node.js 上的并發(fā)性)及其影響。

其次: webflux兼容大部分springmvc的注解,也可以像mvc那樣創(chuàng)建controller處理請(qǐng)求。

區(qū)別:

  • WebFlux是完全異步非阻塞的,SpringMVC是同步阻塞的。
  • WebFlux采用異步響應(yīng)式編程,SpringMVC采用命令式編程。
  • WebFlux由于完全異步,所有操作數(shù)據(jù)庫的框架,以及數(shù)據(jù)庫也都要求是支持異步的,所以目前不支持Mybatis、不支持Oracle數(shù)據(jù)庫。

6. 并發(fā)模型

盡管webmvcwebflux都支持使用注解來定義一個(gè)Controller,但是其實(shí)現(xiàn)方式完全不同。

webmvc是一個(gè)Servlet應(yīng)用,實(shí)現(xiàn)是阻塞式IO,其維護(hù)一個(gè)線程池來處理每一個(gè)用戶請(qǐng)求,也就是當(dāng)Servlet容器啟動(dòng)時(shí),就會(huì)創(chuàng)建比如10個(gè)線程出來,因此系統(tǒng)吞吐量的瓶頸在于有限的連接數(shù)和阻塞的請(qǐng)求處理過程。

webflux可以基于netty這樣的NIO網(wǎng)絡(luò)框架,它只需要很少的幾個(gè)工作線程(Event loop worker)就能夠處理并響應(yīng)請(qǐng)求。由于無需阻塞等待方法返回,CPU資源就得到了更好的利用。

webflux并不能讓程序運(yùn)行地更快;而是提高了并發(fā)處理請(qǐng)求的能力,即提高系統(tǒng)吞吐量。

7. webflux使用

pom依賴:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <version>2.5.9</version>
    </dependency>
</dependencies>

定義對(duì)象:

public class Person {
    private Integer id;
    private Integer age;
    private String name;

    public Person(Integer id, Integer age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

然后定義PersonController,響應(yīng)式風(fēng)格中不再使用@RequestMapping聲明地址映射,而是通過RouterFunctions.route().GET()方法:

@Configuration
public class PersonRouter {
    @Resource
    private PersonHandler personHandler;
    @Bean
    public RouterFunction<ServerResponse> personRoutes() {
        return RouterFunctions.route()
                .GET("/person/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), personHandler::getPerson)
                .GET("/person", RequestPredicates.accept(MediaType.APPLICATION_JSON), personHandler::listPeople)
                .POST("/person", personHandler::createPerson)
                .build();
    }
}

PersonHandler中處理對(duì)應(yīng)的HTTP請(qǐng)求,等同于MVC架構(gòu)中的Service層

@Component
public class PersonHandler {

    @Resource
    private IPersonDao personDao;

    public Mono<ServerResponse> listPeople(ServerRequest request) {
        Flux<Person> people = personDao.getList();
        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(people, Person.class);
    }

    public Mono<ServerResponse> createPerson(ServerRequest request) {
        return request.bodyToMono(Person.class)
                .flatMap(i -> personDao.savePerson(i))
                .flatMap(p -> ServerResponse.ok().bodyValue(p));
    }

    public Mono<ServerResponse> getPerson(ServerRequest request) {
        int personId = Integer.parseInt(request.pathVariable("id"));
        return personDao.getPerson(personId)
                .flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(person))
                .switchIfEmpty(ServerResponse.notFound().build());
    }
}

IPersonDao

public interface IPersonDao {

    /**
     * 獲取所有person
     * @author: yh
     * @date: 2022/9/4
     * @return Flux<Person>
     */
    Flux<Person> getList();

    /**
     * 保存對(duì)象
     * @param person person
     * @author: yh
     * @date: 2022/9/4
     * @return Mono<Void>
     */
    Mono<Void> savePerson(Person person);

    /**
     * 根據(jù)id查詢
     * @param id id
     * @author: yh
     * @date: 2022/9/4
     * @return Mono<Person>
     */
    Mono<Person> getPerson(Integer id);
}

PersonDao

@Component
public class PersonDao implements IPersonDao {

    private final List<Person> personList = new ArrayList<>();

    public PersonDao() {
        this.personList.add(new Person(1, 17, "張三"));
        this.personList.add(new Person(2, 18, "李四"));
    }

    @Override
    public Flux<Person> getList() {
        return Flux.fromIterable(personList);
    }

    @Override
    public Mono<Void> savePerson(Person person) {
        personList.add(person);
        System.out.println("personList.size = " + personList);
        return Mono.empty();
    }

    @Override
    public Mono<Person> getPerson(Integer id) {
        return Mono.justOrEmpty(personList.stream().filter(p -> p.getId().equals(id)).findFirst());
    }
}
@SpringBootApplication
@EnableWebFlux
public class SpringWebfluxSessionApplication implements WebFluxConfigurer {
    public static void main(String[] args) {
        SpringApplication.run(SpringWebfluxSessionApplication.class, args);
    }
}

8. 測(cè)試

通過啟動(dòng)日志可以證實(shí)Spring-webflux是默認(rèn)使用Netty提供HTTP服務(wù)

GET請(qǐng)求:http://127.0.0.1:8080/person

POST請(qǐng)求:http://127.0.0.1:8080/person

boyd:

{
    "id": 9,
    "age": 17,
    "name": "張三"
}

控制臺(tái)輸出:

GET請(qǐng)求:http://127.0.0.1:8080/person/9

完整代碼已上傳 Gitee Spring整合常用組件

到此這篇關(guān)于Spring-webflux 響應(yīng)式編程的文章就介紹到這了,更多相關(guān)Spring webflux 響應(yīng)式編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis中foreach的使用詳解

    Mybatis中foreach的使用詳解

    Mybatis中foreach標(biāo)簽的使用詳解,包括屬性說明、代碼示例和總結(jié),感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • 2020最新版idea激活教程(推薦)

    2020最新版idea激活教程(推薦)

    這篇文章主要介紹了2020最新版idea激活教程,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • SiteMesh如何結(jié)合Freemarker及velocity使用

    SiteMesh如何結(jié)合Freemarker及velocity使用

    這篇文章主要介紹了SiteMesh如何結(jié)合Freemarker及velocity使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 關(guān)于eclipse中運(yùn)行tomcat提示端口被占用的4種解決

    關(guān)于eclipse中運(yùn)行tomcat提示端口被占用的4種解決

    這篇文章主要介紹了關(guān)于eclipse中運(yùn)行tomcat提示端口被占用的4種解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Spring中的@Lazy注解用法實(shí)例

    Spring中的@Lazy注解用法實(shí)例

    這篇文章主要介紹了Spring中的@Lazy注解用法實(shí)例,在Spring中常用于單實(shí)例Bean對(duì)象的創(chuàng)建和使用,單實(shí)例Bean懶加載容器啟動(dòng)后不創(chuàng)建對(duì)象,而是在第一次獲取Bean創(chuàng)建對(duì)象時(shí),初始化,需要的朋友可以參考下
    2023-08-08
  • java GUI實(shí)現(xiàn)加法計(jì)算器

    java GUI實(shí)現(xiàn)加法計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了java GUI實(shí)現(xiàn)加法計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 詳解Java8新特性之interface中的static方法和default方法

    詳解Java8新特性之interface中的static方法和default方法

    這篇文章主要介紹了Java8新特性之interface中的static方法和default方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-08-08
  • 利用Spring JPA中的@Version注解實(shí)現(xiàn)樂觀鎖

    利用Spring JPA中的@Version注解實(shí)現(xiàn)樂觀鎖

    樂觀鎖是數(shù)據(jù)庫和應(yīng)用程序中使用的一種并發(fā)控制策略,用于在多個(gè)事務(wù)嘗試更新單個(gè)記錄時(shí)確保數(shù)據(jù)完整性,Java Persistence API (JPA) 提供了一種借助@Version注解在 Java 應(yīng)用程序中實(shí)現(xiàn)樂觀鎖的機(jī)制,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2023-11-11
  • java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu)詳解

    java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu)詳解

    這篇文章主要介紹了java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java使用Rxtx實(shí)現(xiàn)串口通信調(diào)試工具

    java使用Rxtx實(shí)現(xiàn)串口通信調(diào)試工具

    這篇文章主要為大家詳細(xì)介紹了java使用Rxtx實(shí)現(xiàn)簡(jiǎn)單串口通信調(diào)試工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12

最新評(píng)論

河曲县| 双牌县| 闸北区| 青海省| 奇台县| 大化| 曲麻莱县| 洪江市| 安国市| 抚松县| 大化| 青河县| 湾仔区| 天祝| 探索| 蒙自县| 盐亭县| 务川| 裕民县| 穆棱市| 桐城市| 阳江市| 宁河县| 辽源市| 芜湖县| 京山县| 雅江县| 霍邱县| 阳信县| 聊城市| 合川市| 永城市| 神农架林区| 资中县| 呼和浩特市| 云阳县| 根河市| 贡山| 广饶县| 常德市| 新巴尔虎右旗|