Spring WebFlux is the new module introduced in Spring 5. Spring WebFlux is the first step towards reactive programming model in spring framework.

Spring WebFlux是Spring 5中引入的新模块。SpringWebFlux是向Spring框架中的React式编程模型迈出的第一步。

弹簧React式编程 (Spring Reactive Programming)

If you are new to reactive programming model, then I would highly suggest you to go through following articles to learn about reactive programming.

如果您不熟悉React式编程模型,那么我强烈建议您阅读以下文章以了解React式编程。

  • Reactive Manifesto
    React式宣言
  • Reactive Streams
    React流
  • Java 9 Reactive Streams
    Java 9React流
  • RxJava
    RxJava的

If you are new to Spring 5, please go through Spring 5 Features.

如果您不熟悉Spring 5,请参阅Spring 5功能 。

SpringWebFlux (Spring WebFlux)

Spring WebFlux is the alternative to Spring MVC module. Spring WebFlux is used to create fully asynchronous and non-blocking application built on event-loop execution model.

Spring WebFlux是Spring MVC模块的替代方案。 Spring WebFlux用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。

Below diagram from Spring Official Documentation provides great insight on comparison of Spring WebFlux to Spring Web MVC.

Spring官方文档中的下图提供了关于Spring WebFlux与Spring Web MVC比较的深刻见解。

If you are looking to develop a web application or Rest web service on non-blocking reactive model, then you can look into Spring WebFlux.

如果您希望在非阻塞React模型上开发Web应用程序或Rest Web服务,那么可以研究Spring WebFlux。

Spring WebFlux is supported on Tomcat, Jetty, Servlet 3.1+ containers, as well as on non-Servlet runtimes such as Netty and Undertow.

Tomcat,Jetty,Servlet 3.1+容器以及Netty和Undertow等非Servlet运行时都支持Spring WebFlux。

Spring WebFlux is built on Project Reactor. Project Reactor is the implementation of Reactive Streams specification. Reactor provides two types:

Spring WebFlux基于Project Reactor构建。 Project Reactor是Reactive Streams规范的实现。 Reactor提供两种类型:

  1. Mono: implements Publisher and returns 0 or 1 elements
    Mono :实现Publisher,并返回0或1个元素
  2. Flux: implements Publisher and returns N elements.
    Flux :实现Publisher,并返回N个元素。

Spring WebFlux Hello World示例 (Spring WebFlux Hello World Example)

Let’s built a simple Spring WebFlux Hello World application. We will create a simple rest web service and use Spring Boot to run it on default Netty server.

让我们构建一个简单的Spring WebFlux Hello World应用程序。 我们将创建一个简单的rest Web服务,并使用Spring Boot在默认的Netty服务器上运行它。

Our final project structure looks like below image.

我们的最终项目结构如下图所示。

Let’s look into each component of the application one by one.

让我们逐一研究应用程序的每个组件。

Spring WebFlux Maven依赖关系 (Spring WebFlux Maven Dependencies)

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.journaldev.spring</groupId><artifactId>SpringWebflux</artifactId><version>0.0.1-SNAPSHOT</version><name>Spring WebFlux</name><description>Spring WebFlux Example</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><jdk.version>1.9</jdk.version></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope></dependency></dependencies><repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><snapshots><enabled>true</enabled></snapshots></repository><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories><pluginRepositories><pluginRepository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><snapshots><enabled>true</enabled></snapshots></pluginRepository><pluginRepository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></pluginRepository></pluginRepositories><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.7.0</version><configuration><source>${jdk.version}</source><target>${jdk.version}</target></configuration></plugin></plugins></pluginManagement></build></project>

The most important dependencies are spring-boot-starter-webflux and spring-boot-starter-parent. Some other dependencies are for creating JUnit test cases.

最重要的依赖项是spring-boot-starter-webfluxspring-boot-starter-parent 。 其他一些依赖关系是用于创建JUnit测试用例的。

Spring WebFlux处理程序 (Spring WebFlux Handler)

Spring WebFlux Handler method handles the request and returns Mono or Flux as response.

Spring WebFlux Handler方法处理请求并返回MonoFlux作为响应。

package com.journaldev.spring.component;import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Mono;@Component
public class HelloWorldHandler {public Mono<ServerResponse> helloWorld(ServerRequest request) {return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("Hello World!"));}
}

Notice that reactive component Mono holds the ServerResponse body. Also look at the function chain to set the return content type, response code and body.

注意,React组件Mono拥有ServerResponse主体。 还要查看功能链,以设置返回内容类型,响应代码和主体。

Spring WebFlux路由器 (Spring WebFlux Router)

Router method are used to define routes for the application. These methods return RouterFunction object that also holds ServerResponse body.

路由器方法用于定义应用程序的路由。 这些方法返回同样包含ServerResponse主体的RouterFunction对象。

package com.journaldev.spring.component;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;@Configuration
public class HelloWorldRouter {@Beanpublic RouterFunction<ServerResponse> routeHelloWorld(HelloWorldHandler helloWorldHandler) {return RouterFunctions.route(RequestPredicates.GET("/helloWorld").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloWorldHandler::helloWorld);}
}

So we are exposing a GET method for /helloWorld and the client call should accept plain text response.

因此,我们公开了/helloWorld的GET方法,并且客户端调用应接受纯文本响应。

Spring Boot应用程序 (Spring Boot Application)

Let’s configure our simple WebFlux application with Spring Boot.

让我们使用Spring Boot配置我们的简单WebFlux应用程序。

package com.journaldev.spring;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

If you look at above code, there is nothing related to Spring WebFlux. But Spring Boot will configure our application as Spring WebFlux since we have added dependency of spring-boot-starter-webflux module.

如果您看上面的代码,则与Spring WebFlux没有任何关系。 但是Spring Boot会将我们的应用程序配置为Spring WebFlux,因为我们添加了spring-boot-starter-webflux模块的依赖项。

Java 9模块支持 (Java 9 Modules Support)

Our application is ready to execute on Java 8, but if you are using Java 9 then we also need to add module-info.java class.

我们的应用程序已准备好在Java 8上执行,但是如果您使用的是Java 9,那么我们还需要添加module-info.java类。

module com.journaldev.spring {requires reactor.core;requires spring.web;requires spring.beans;requires spring.context;requires spring.webflux;requires spring.boot;requires spring.boot.autoconfigure;exports com.journaldev.spring;
}

运行Spring WebFlux Spring Boot App (Running the Spring WebFlux Spring Boot App)

If you have Spring support in Eclipse, then you can run above class as Spring Boot App.

如果您在Eclipse中具有Spring支持,则可以在类之上运行Spring Boot App。

If you like to use command line, then open terminal and run command mvn spring-boot:run from the project source directory.

如果要使用命令行,请打开终端,然后从项目源目录运行命令mvn spring-boot:run

Once the app is running, notice following log messages to make sure everything is good with our app. It’s also helpful when you extend this simple app by adding more routes and functionalities.

应用程序运行后,请注意以下日志消息,以确保我们的应用程序一切正常。 当您通过添加更多路由和功能扩展此简单应用程序时,它也很有帮助。

2018-05-07 15:01:47.893  INFO 25158 --- [           main] o.s.w.r.f.s.s.RouterFunctionMapping      : Mapped ((GET && /helloWorld) && Accept: ) -> com.journaldev.spring.component.HelloWorldRouter$$Lambda$501/704766954@6eeb5d56
2018-05-07 15:01:48.495  INFO 25158 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-05-07 15:01:48.495  INFO 25158 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-05-07 15:01:48.501  INFO 25158 --- [           main] com.journaldev.spring.Application        : Started Application in 1.86 seconds (JVM running for 5.542)

It’s clear from logs that our app is running on Netty server on port 8080. Let’s go ahead and test our application.

从日志中很明显,我们的应用程序正在端口8080的Netty服务器上运行。让我们继续测试我们的应用程序。

SpringWebFlux App测试 (Spring WebFlux App Test)

We can test our app with various methods.

我们可以通过多种方法测试我们的应用。

  1. Using CURL command

    $ curl https://localhost:8080/helloWorld
    Hello World!
    $

    使用CURL命令

  2. Launch URL in Browser

    在浏览器中启动URL

  3. Using WebTestClient from Spring 5

    Here is a JUnit test program to test our Rest web service using WebTestClient from Spring 5 reactive web.

    package com.journaldev.spring;import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.reactive.server.WebTestClient;@RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class SpringWebFluxTest {@Autowiredprivate WebTestClient webTestClient;@Testpublic void testHelloWorld() {webTestClient.get().uri("/helloWorld") // GET method and URI.accept(MediaType.TEXT_PLAIN) //setting ACCEPT-Content.exchange() //gives access to response.expectStatus().isOk() //checking if response is OK.expectBody(String.class).isEqualTo("Hello World!"); // checking for response type and message}}

    Run it a JUnit test case and it should pass with flying colors.

    从Spring 5开始使用WebTestClient

    这是一个JUnit测试程序,用于使用Spring 5响应式Web中的WebTestClient测试我们的Rest Web服务。

    package com.journaldev.spring;import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.reactive.server.WebTestClient;@RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class SpringWebFluxTest {@Autowiredprivate WebTestClient webTestClient;@Testpublic void testHelloWorld() {webTestClient.get().uri("/helloWorld") // GET method and URI.accept(MediaType.TEXT_PLAIN) //setting ACCEPT-Content.exchange() //gives access to response.expectStatus().isOk() //checking if response is OK.expectBody(String.class).isEqualTo("Hello World!"); // checking for response type and message}}

    运行它一个JUnit测试用例,它应该以飞快的速度通过。

  4. Using WebClient from Spring Web Reactive

    We can also use WebClient to call the REST web service.

    package com.journaldev.spring.client;import org.springframework.http.MediaType;
    import org.springframework.web.reactive.function.client.ClientResponse;
    import org.springframework.web.reactive.function.client.WebClient;import reactor.core.publisher.Mono;public class HelloWorldWebClient {public static void main(String args[]) {WebClient client = WebClient.create("https://localhost:8080");Mono<ClientResponse> result = client.get().uri("/helloWorld").accept(MediaType.TEXT_PLAIN).exchange();System.out.println("Result = " + result.flatMap(res -> res.bodyToMono(String.class)).block());}}

    Just run it as a simple java application and you should see the proper output with a lot of debug messages.

    从Spring Web Reactive使用WebClient

    我们还可以使用WebClient来调用REST Web服务 。

    package com.journaldev.spring.client;import org.springframework.http.MediaType;
    import org.springframework.web.reactive.function.client.ClientResponse;
    import org.springframework.web.reactive.function.client.WebClient;import reactor.core.publisher.Mono;public class HelloWorldWebClient {public static void main(String args[]) {WebClient client = WebClient.create("https://localhost:8080");Mono<ClientResponse> result = client.get().uri("/helloWorld").accept(MediaType.TEXT_PLAIN).exchange();System.out.println("Result = " + result.flatMap(res -> res.bodyToMono(String.class)).block());}}

    只需将其作为一个简单的Java应用程序运行即可,您应该看到带有大量调试消息的正确输出。

摘要 (Summary)

In this post we learned about Spring WebFlux and how to build a hello world reactive Restful web service.

在这篇文章中,我们了解了Spring WebFlux以​​及如何构建一个Hello WorldReact式Restful Web服务。

It’s good to see that popular frameworks such as Spring are rooting for reactive programming model. But we have a lot to cover because if all your dependencies are not reactive and non-blocking then your application is also not truly reactive.

很高兴看到诸如Spring之类的流行框架正在扎根于React式编程模型。 但是我们有很多要讨论的内容,因为如果您的所有依赖项都不是React性和非阻塞的,那么您的应用程序也不是真正的React性。

For example, relational database vendors doesn’t have reactive drivers because they depend on JDBC, that is not reactive. Hence Hibernate API is also non-reactive. So if you are using relational databases then you can’t built a truly reactive application, yet. I am hopeful that it will change sooner than later.

例如,关系数据库供应商没有响应式驱动程序,因为它们依赖JDBC,而后者不是响应式的。 因此,Hibernate API也是非React性的。 因此,如果您正在使用关系数据库,那么您还不能构建真正的React式应用程序。 我希望它将早日改变。

GitHub Repository.GitHub Repository下载项目代码。

Reference: Official Documentation

参考: 官方文档

翻译自: https://www.journaldev.com/20763/spring-webflux-reactive-programming

Spring WebFlux – SpringReact式编程相关推荐

  1. Spring WebFlux 响应式编程学习笔记(一)

    各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了Spring WebFl ...

  2. Spring Webflux 响应式编程 (二) - WebFlux编程实战

    第一章 Reactive Stream 第1节 jdk9的响应式流 就是reactive stream,也就是flow.其实和jdk8的stream没有一点关系.说白了就一个发布-订阅模式,一共只有4 ...

  3. Spring web-flux 响应式编程

    1.基于传统的结构 Demo (仅仅作为快速了解,生产环境不会用这种) 请求处理类 Controller 类 package com.yootk.webflux.handler; import org ...

  4. Spring:Webflux响应式编程

    目录 简介 响应式编程 Reactor 信号 操作符 SpringWebflux 执行流程和API 注解实现SpringWebflux 说明:基于atguigu学习笔记. 简介 Webflux是 Sp ...

  5. WebFlux响应式编程

    文章目录 概要 入门WebFlux WebClient 概要 在SpringMvc框架下,http的请求是同步的,在某些场景下为了提供性能,可以采用异步的方式来进行优化.WebFlux便是提供了异步的 ...

  6. WebFlux响应式编程基础之 2 函数式编程 工具jclasslib bytecode viewer

    函数式编程:告诉他的功能是什么,而不是告诉他怎么做 命令式编程:怎么去做 函数式编程:不需要关注细节,利用系统已经有的API 使用jdk8自带函数接口的好处 函数接口减少接口定义 函数式接口链式操作 ...

  7. WebFlux响应式编程基础之 5 webflux服务端开发讲解

    https://blog.csdn.net/qq_27093465/article/details/64124330 debug技巧 第5章 webflux服务端开发讲解 Spring5 非组塞的开发 ...

  8. flux服务器推消息,在Spring WebFlux响应式处理程序中发送JMS消息:它是否阻塞?

    这是反应性处理的正确方法吗?我看到2个线程一个反应性的nio,直到并包括flatMap(fareRepo :: save).另一个线程是计算线程,它从发送消息开始,一直持续到ServerRespons ...

  9. WebFlux响应式编程基础之 4 reactive stream 响应式流

    reactive stream 响应式流 - 简而言之,就是多了一个沟通的渠道 发布订阅者 背压 交流 Reactive Stream主要接口 java.util.concurrent.Flow 源码 ...

最新文章

  1. 【Effective Java】1.静态工厂方法来替换构造函数
  2. sonarqube下安装mysql数据库_本地安装SonarQube之一——win7环境安装mysql
  3. 图解用Fiddler做http协议分析入门
  4. Java源码解析:hashCode与相同对象的关系
  5. 如何解决用伪元素点击下拉列表触发不了事件的问题
  6. Java的GC机制及算法
  7. 如何查看node的版本及安装的位置?
  8. PANEL中显示窗体
  9. 【HDU - 5056】Boring count (尺取法)
  10. yii2实现WebService 使用 SoapDiscovery
  11. ad采样做按键开关_基于ad采样电路的多路开关量采集装置及其采集方法
  12. 关于Latex出现Package CJK Error
  13. LVDS通信协议以及概念
  14. MapReduce的核心资料索引
  15. 红警ol服务器维护中1003,红警OL频繁掉线怎们么办 网络断开连接解决办法
  16. 博弈论--取石子游戏
  17. c 语言 时间间隔(多实例测试)
  18. 基于心电芯片 KS1081的微小穿戴心电方案
  19. Mysql数据库【触发器】
  20. border-radius 使用技巧

热门文章

  1. excel批量导入数据
  2. ASP.NET程序中常用代码汇总-1
  3. [转载] python 如何判断中文的字符串长度
  4. JS编写自己的富文本编辑器
  5. PHP curl函数制 exec_ch和get_headers
  6. 数据结构笔记(八)-- 链式栈
  7. vc++数字图像处理 自适应二值化程序
  8. 查询系统linux命令,Linux系统下基本的帮助查询命令小结
  9. 虚拟服务器的密码忘记了,忘记虚拟密码
  10. django在window和linux,从windows导入Django项目到linux时出错