引子:被誉为“中国大数据第一人”的涂子沛先生在其成名作《数据之巅》里提到,摩尔定律、社交媒体、数据挖掘是大数据的三大成因。IBM的研究称,整个人类文明所获得的全部数据中,有90%是过去两年内产生的。在此背景下,包括NoSQL,Hadoop, Spark, Storm, Kylin在内的大批新技术应运而生。其中以RxJava和Reactor为代表的响应式(Reactive)编程技术针对的就是经典的大数据4V定义(Volume,Variety,Velocity,Value)中的Velocity,即高并发问题,而在即将发布的Spring 5中,也引入了响应式编程的支持。在接下来的几周,我会围绕响应式编程分三期与你分享我的一些学习心得。本篇是第三篇,通过一个简单的Spring 5示例应用,探一探即将于下月底发布的Spring 5的究竟。

前情概要:

  • 【Spring 5】响应式Web框架前瞻

  • 响应式编程总览

1 回顾

通过前两篇的介绍,相信你对响应式编程和Spring 5已经有了一个初步的了解。下面我将以一个简单的Spring 5应用为例,介绍如何使用Spring 5快速搭建一个响应式Web应用(以下简称RP应用)。

2 实战

2.1 环境准备

首先,从GitHub下载我的这个示例应用,地址是https://github.com/emac/spring5-features-demo。

然后,从MongoDB官网下载最新版本的MongoDB,然后在命令行下运行mongod &启动服务。

现在,可以先试着跑一下项目中自带的测试用例。

./gradlew clean build

2.2 依赖介绍

接下来,看一下这个示例应用里的和响应式编程相关的依赖。

compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')
testCompile('io.projectreactor.addons:reactor-test')
  • spring-boot-starter-webflux: 启用Spring 5的RP(Reactive Programming)支持,这是使用Spring 5开发RP应用的必要条件,就好比spring-boot-starter-web之于传统的Spring MVC应用。

  • spring-boot-starter-data-mongodb-reactive: Spring 5中新引入的针对MongoDB的Reactive Data扩展库,允许通过统一的RP风格的API操作MongoDB。

  • io.projectreactor.addons:reactor-test: Reactor(Spring 5默认使用的RP框架)提供的官方测试工具库。

2.3 示例代码

不知道你是否还记得,在本系列第一篇【Spring 5】响应式Web框架前瞻里提到,Spring 5提供了Spring MVC注解和Router Functions两种方式来编写RP应用。本篇我就先用大家最熟悉的MVC注解来展示如何编写一个最简单的RP Controller。

@RestController
public class RestaurantController {/*** 扩展ReactiveCrudRepository接口,提供基本的CRUD操作*/private final RestaurantRepository restaurantRepository;/*** spring-boot-starter-data-mongodb-reactive提供的通用模板*/private final ReactiveMongoTemplate reactiveMongoTemplate;public RestaurantController(RestaurantRepository restaurantRepository, ReactiveMongoTemplate reactiveMongoTemplate) {this.restaurantRepository = restaurantRepository;this.reactiveMongoTemplate = reactiveMongoTemplate;}@GetMapping("/reactive/restaurants")public Flux<Restaurant> findAll() {return restaurantRepository.findAll();}@GetMapping("/reactive/restaurants/{id}")public Mono<Restaurant> get(@PathVariable String id) {return restaurantRepository.findById(id);}@PostMapping("/reactive/restaurants")public Flux<Restaurant> create(@RequestBody Flux<Restaurant> restaurants) {return restaurants.buffer(10000).flatMap(rs -> reactiveMongoTemplate.insert(rs, Restaurant.class));}@DeleteMapping("/reactive/restaurants/{id}")public Mono<Void> delete(@PathVariable String id) {return restaurantRepository.deleteById(id);}
}

可以看到,实现一个RP Controller和一个普通的Controller是非常类似的,最核心的区别是,优先使用RP中最基础的两种数据类型,Flux(对应多值)和Mono(单值),尤其是方法的参数和返回值。即便是空返回值,也应封装为Mono<Void>。这样做的目的是,使得应用能够以一种统一的符合RP规范的方式处理数据,最理想的情况是从最底层的数据库(或者其他系统外部调用),到最上层的Controller层,所有数据都不落地,经由各种FluxMono铺设的“管道”,直供调用端。就像农夫山泉那句著名的广告词,我们不生产水,我们只是大自然的搬运工。

2.4 单元测试

和非RP应用的单元测试相比,RP应用的单元测试主要是使用了一个Spring 5新引入的测试工具类,WebTestClient,专门用于测试RP应用。

@RunWith(SpringRunner.class)
@SpringBootTest
public class RestaurantControllerTests {@Testpublic void testNormal() throws InterruptedException {// start from scratchrestaurantRepository.deleteAll().block();// prepareWebTestClient webClient = WebTestClient.bindToController(new RestaurantController(restaurantRepository, reactiveMongoTemplate)).build();Restaurant[] restaurants = IntStream.range(0, 100).mapToObj(String::valueOf).map(s -> new Restaurant(s, s, s)).toArray(Restaurant[]::new);// createwebClient.post().uri("/reactive/restaurants").accept(MediaType.APPLICATION_JSON_UTF8).syncBody(restaurants).exchange().expectStatus().isOk().expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8).expectBodyList(Restaurant.class).hasSize(100).consumeWith(rs -> Flux.fromIterable(rs).log().subscribe(r1 -> {// getwebClient.get().uri("/reactive/restaurants/{id}", r1.getId()).accept(MediaType.APPLICATION_JSON_UTF8).exchange().expectStatus().isOk().expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8).expectBody(Restaurant.class).consumeWith(r2 -> Assert.assertEquals(r1, r2));}));}
}

创建WebTestClient实例时,首先要绑定一下待测试的RP Controller。可以看到,和业务类一样,编写RP应用的单元测试,同样也是数据不落地的流式风格。

在示例应用中可以找到更多的单元测试。

3 小结

以上就是Spring 5里第一种,相信也将会是最常用的编写RP应用的实现方式。介于篇幅原因,这篇就先到这里。下篇我将详细介绍第二种方式,Router Functions。欢迎你到我的留言板分享,和大家一起过过招。

4 参考

  • Spring Framework Reference - WebFlux framework

  • spring-framework Reactive Tests

【Spring 5】响应式Web框架实战(上) 1相关推荐

  1. 【Spring 5】响应式Web框架实战(下)

    - [Spring 5]响应式Web框架前瞻  - 响应式编程总览  - [Spring 5]响应式Web框架实战(上) 1 回顾 上篇介绍了如何使用Spring MVC注解实现一个响应式Web应用( ...

  2. 【Spring 5】响应式Web框架实战(上)

    前情概要:  - [Spring 5]响应式Web框架前瞻  - 响应式编程总览 1 回顾 通过前两篇的介绍,相信你对响应式编程和Spring 5已经有了一个初步的了解.下面我将以一个简单的Sprin ...

  3. 【Spring 5】响应式Web框架前瞻

    1 响应式宣言 和敏捷宣言一样,说起响应式编程,必先提到响应式宣言. We want systems that are Responsive, Resilient, Elastic and Messa ...

  4. 艿艿连肝了几个周末,写了一篇贼长的 Spring 响应式 Web 框架 WebFlux!市面第二完整~...

    点击上方"芋道源码",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~ 中文详细注释的开源项目 RP ...

  5. java局部网内通话杂音_在Spring Boot反应式Web应用程序上启用SSL,并在控制台中对该打印进行http调用时出现异常噪音...

    在我创建了我的spring boot反应式Web应用程序以支持SSL之后,当我尝试对服务器进行http调用时,它会在控制台中的异常跟踪下面打印 . 作为应用程序所有者,我无法阻止任何人使用我的服务 . ...

  6. 艿艿连肝了几个周末,写了一篇贼长的 Spring 响应式 Web 框架 WebFlux!市面第二完整~

    本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-27 目录. 原创不易,给点个 Star 嘿,一起冲鸭! 1. 概述 友情 ...

  7. Vert.x 响应式 Web 框架介绍使用

    一.Vert.x 简介 Vert.x 是JVM上构建 响应式 应用的工具. 响应式应用既可以随着工作负载的增长而 扩展 ,又可以在出现故障时 弹性回复 . 响应式应用是 即时响应 的,因为它能有效利用 ...

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

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

  9. 适用响应式 Web UI 框架

    1. Bootstrap Bootstrap是快速开发Web应用程序的前端工具包.它是一个CSS和HTML的集合,它使用了最新的浏览器技术,给你的Web开发提供了时尚的版式,表单,buttons,表格 ...

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

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

最新文章

  1. 【FFmpeg】设置H264参数
  2. Javaweb 实验二 JSP应用开发基础
  3. Exchange Server 2010 全新部署篇八:CASHUB中集线器配置部分
  4. JS 禁用键盘按钮
  5. 使用条件注释完成浏览器兼容
  6. Visio 使用心得
  7. Telink Mesh 开发(1)调试log打印
  8. 2018携程实习生大数据分析笔试练习题
  9. CMSC5724-数据挖掘之VC维、Shatter、VC-dim以及Margin有关的通理
  10. 微信小程序相关操作示例
  11. Android MediaPlayer使用注意
  12. 水果店线上引流推广方案,水果店线上运营是做些什么
  13. Android 手机采集摄像头视频 socket 视频传输实时传播
  14. C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)
  15. (转载)技术族谱:软件开发相关知识体系的整理心得(图)
  16. 什么是加密?有哪些加密类型和加密算法?
  17. Android 音频驱动分析--A10
  18. 人类最美的24张数学画(图),让你觉得吊炸天【文末有福利】
  19. PhotoImpact amp;Microsoft Access
  20. nfs只能挂载为nobody的解决方法

热门文章

  1. Wpf从资源中重用UI元素
  2. PHP无限极分类巧用引用生成树
  3. ApiDemos示例学习(1)——ApiDemos示例的导入
  4. php实现禁止缓存,高手莫来
  5. 博客园 使用锚和书签制作目录
  6. Linux学习笔记之查看Linux版本信息
  7. Django 添加应用
  8. [网络流24题] 最长k可重线段集问题 (费用流)
  9. Linux下七牛云存储qrsync命令行上传同步工具
  10. Linux导出/导入逻辑卷组信息