收藏|spring5.0响应式编程入门

Posted 黑马程序员广州中心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了收藏|spring5.0响应式编程入门相关的知识,希望对你有一定的参考价值。

引言

响应式编程是一种面向数据流和变化传播的编程范式。使用它可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。我们可以使用声明的方式构建应用程序的能力,形成更加敏感和有弹性的应用,所以Spring 5在其核心框架中增加了反应系统,已经开始向声明式编程的范式转变。

响应式编程的优势


  • 提高了代码的可读性,因此开发人员只需要关注定义业务逻辑。

  • 在高并发环境中,可以自然的处理消息。

  • 可以控制生产者和消费者之间的流量,避免内存不足。

  • 对于一个或多个线程,IO绑定任务可以通过异步和非阻塞方式执行,而且不阻塞当前线程。

  • 可以有效的管理多个连接系统之间的通信。

应用场景


• 大量的交易处理服务,如银行部门。

• 大型在线购物应用程序的通知服务,如亚马逊。

• 股票价格同时变动的股票交易业务。

Spring 5.0前瞻

作为Java中的首个响应式Web框架,Spring 5.0最大的亮点莫过于提供了完整的端到端响应式编程的支持。 


收藏|spring5.0响应式编程入门

如上图所示左侧是传统的基于Servlet的Spring Web MVC框架,右侧是spring 5.0新引入的基于Reactive Streams的Spring WebFlux框架,从上往下依次是:Router Functions,WebFlux,Reactive Streams三个新组件,其中:

  • Router Functions: 对标@Controller,@RequestMapping等标准的Spring MVC注解,提供一套函数式风格的API,用于创建Router,Handler和Filter。

  • WebFlux: 核心组件,协调上下游各个组件提供响应式编程支持。

  • Reactive Streams: 一种支持背压(Backpressure)的异步数据流处理标准,主流实现有RxJava和Reactor,Spring WebFlux默认集成的是Reactor。



示例代码


1.创建项目

spring响应式开发,需要结合spring boot来完成,所以使用idea创建springboot项目,选择Spring Initializr选项,jdk选择1.8以上。


  收藏|spring5.0响应式编程入门


选择下一步,设置groupId和artifactId。

  收藏|spring5.0响应式编程入门


选择下一步,选择web选项中的Reactive web选项,表明要创建响应式项目,注意Spring Boot的版本为2.0.2。

  收藏|spring5.0响应式编程入门


选择下一步,设置项目的目录,点击finish创建项目。

  收藏|spring5.0响应式编程入门


2.设置服务端口

为了避免端口冲突,我们可以在项目的application.properties文件中配置服务端口。

server.port=9002


3.相关依赖包

打开项目的pom.xml文件,会发现以下几个依赖包

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


其中:

  • spring-boot-starter-webflux:webflux依赖包,是响应式开发的核心依赖包,其中包含了spring-boot-starter-reactor-netty 、spring 5 webflux 包,默认是通过netty启动的。

  • spring-boot-starter-test:springboot的单元测试工具库。

  • reactor-test:Spring 5提供的官方针对RP框架测试工具库。


小结

spring响应式开发需要结合spring boot来完成,同时需要引入spring-boot-starter-webflux和reactor-test两个依赖包来支持响应式开发。


4.使用webflux创建web应用

webflux的使用有两种方式,基于注解和函数式编程。这里使用函数式编程,具体操作如下:

4.1.创建实体类

public class Good {

   private int id;
   private String name;
   private String price;

   public Good(int id,String name,String price){
       this.id=id;
       this.name=name;
       this.price=price;
   }

   public int getId() {
       return id;
   }

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

   public String getName() {
       return name;
   }

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

   public String getPrice() {
       return price;
   }

   public void setPrice(String price) {
       this.price = price;
   }

   @Override
   public String toString() {
       return "Good{" +
               "id=" + id +
               ", name='" + name + ''' +
               ", price='" + price + ''' +
               '}';
   }
}

分析:  实体类没有什么特殊的操作,原来怎么操作现在还是怎么操作。


4.2.创建GoodGenerator

@Configuration
public class GoodGenerator {

   public Flux<Good> findGoods(){
       List<Good> goods = new ArrayList<>();
       goods.add(new Good(1,"小米","2000"));
       goods.add(new Good(2,"华为","4000"));
       goods.add(new Good(3,"苹果","8000"));
       return Flux.fromIterable(goods);
   }
}

分析:  这里的方法返回的是Flux类型的数据,Flux是RP中最基础的数据类型之一,对应的是多值数据的返回操作,在RP中还有Mono数据类型,也是最基础的数据类型之一,对应单值数据的返回操作。

注意:这里的GoodGenerator类要加上@Configuration注解。


4.3.创建GoodHandler

@Component
@Configuration
public class GoodHandler {

   private final Flux<Good> goods;

   public GoodHandler(GoodGenerator goodGenerator) {
       this.goods = goodGenerator.findGoods();
   }

   public Mono<ServerResponse> hello(ServerRequest request) {

       return ok().contentType(TEXT_PLAIN)
               .body(BodyInserters.fromObject("Hello Spring!"));
   }

   public Mono<ServerResponse> echo(ServerRequest request) {
       return ok().contentType(APPLICATION_STREAM_JSON)
               .body(this.goods,Good.class);
   }
}

分析:  Handler主要用来处理请求操作,并将Mono返回,Mono中会封装响应数据,响应数据如果是字符串可以使用:

ok().contentType(TEXT_PLAIN).body(BodyInserters.fromObject("Hello Spring!"));

操作,如果是集合数据可以使用:

ok().contentType(APPLICATION_STREAM_JSON).body(this.goods,Good.class)

操作。


4.4.创建GoodRouter

@Configuration
public class GoodRouter {
   @Bean
   public RouterFunction<ServerResponse> route(GoodHandler goodHandler) {

     return RouterFunctions
             .route(RequestPredicates.GET("/good")
                     .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),goodHandler::hello)
             .andRoute(RequestPredicates.GET("/goods")
                     .and(RequestPredicates.accept(MediaType.APPLICATION_STREAM_JSON)),goodHandler::echo);
   }

}

分析:  GoodRouter主要用来设置请求路径和转化HTTP请求,可以使用route()方法和andRoute方法设置多个请求路径和转化操作。

小结

HTTP请求会由GoodRouter转发给对应的Handler,Handler处理请求,并返回Mono,这里的Router类似@RequestMapping,Handler类似Controller


4.4.运行测试

实体类、GoodGenerator、GoodHandler、GoodRouter都已经创建完成了,我们可以运行项目打开浏览器进行测试.

浏览器输入http://localhost:9002/good,即可获取到"Hello Spring!"文本信息


收藏|spring5.0响应式编程入门


浏览器输入http://localhost:9002/goods,即可获取到集合信息

收藏|spring5.0响应式编程入门

到目前为止,一个简单的webflux示例已经完成。


4.5.单元测试

在项目中我们也可以使用使用一个Spring 5新引入的测试工具类,WebTestClient,专门用于测试RP应用,具体代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Spring5demoApplicationTests {

   @Autowired
   private WebTestClient webTestClient;

   @Test
   public void helloTest() {
     String s=  webTestClient
               .get().uri("/good")
               .accept(MediaType.TEXT_PLAIN).exchange()
         .expectStatus().isOk().returnResult(String.class)
         .getResponseBody().blockFirst();

       System.out.println(s);
   }

   @Test
   public void findGoodsTest(){
       webTestClient.get().uri("/goods")
               .accept(MediaType.APPLICATION_STREAM_JSON)
               .exchange().expectStatus().isOk()
           .expectHeader().contentType(MediaType.APPLICATION_STREAM_JSON)
               .returnResult(Good.class)
               .getResponseBody().collectList();
   }
}

创建WebTestClient实例时可以看到,编写RP应用的单元测试,同样也是数据不落地的流式风格。

总结

到此,spring 5.0的响应式编程就给大家介绍到这里,这里只是简单进行了一个响应式入门操作,但是也能够体现出响应式编程的特点。当然spring 5.0响应式编程也不是完美的,它在故障诊断、依赖库集成、数据存储以及Spring Security安全权限框架支持等方面还是有局限性的。  

收藏|spring5.0响应式编程入门
收藏|spring5.0响应式编程入门

 私人微信ID:Andyswen

 想和小娜姐深度交流的可以加好友哦

推荐阅读:




欢迎大家来约小娜QQ

以上是关于收藏|spring5.0响应式编程入门的主要内容,如果未能解决你的问题,请参考以下文章

响应式Spring的道法术器(Spring WebFlux 快速上手 + 全面介绍)

响应式编程系列:什么是响应式编程?reactor入门

RxJS入门之函数响应式编程

响应式编程入门(RxJava)

Spring Boot (十四): 响应式编程以及 Spring Boot Webflux 快速入门

iOS 中的链式编程函数式编程入门