如果您处理大量流数据,反应性应用程序可以让您更好地扩展。它们是非阻塞的,并且往往更有效率,因为它们在等待事情发生时不会占用处理。
反应系统包含异步I / O. 异步I / O背后的概念很简单:通过回收资源来缓解低效的资源利用率,否则这些资源在等待I / O活动时会处于空闲状态。异步I / O反转了I / O处理的正常设计:客户端会收到新数据的通知而不是主动请求拉取数据; 这样可以让客户端在等待数据通知来之前做其他事情。
如果您要构建一个响应式应用程序,您将需要它一直Reactive到您的数据库。在Spring WebFlux中使用阻塞JDBC驱动程序,你会对其性能感到失望。使用像Cassandra,MongoDB,Couchbase和Redis这样的反应性NoSQL数据库 - 你则会对它的性能印象深刻。
在本教程中,您将学习如何使用Spring Boot,Spring WebFlux和Spring Data创建一个与NoSQL数据库后端(在本例中为MongoDB)对话的响应式Web服务。
什么是NoSQL以及为什么选择MongoDB?
NoSQL是任何非关系数据库的术语。在关系数据库(想想SQL,MySQL等等)中,数据存储在表格列中具有强类型和明确定义的关系的表中。关系数据库的紧密,明确的结构既是他们的优势,也是他们的弱点。这是一种权衡。NoSQL数据库打破了这个模型,并提供了其他模型,允许更大的灵活性和易于扩展。
缩放的微服务/集群模型为关系数据库带来了许多问题。它们不是为了在多台机器上运行并保持数据同步而构建的。而部分地使用NoSQL数据库可以来解决这个问题,通常,NoSQL在构建时考虑了聚合类和水平缩放。
NoSQL数据库的另一个潜在好处是它们的灵活性。像MongoDB这样的基于文档的NoSQL数据库可以在文档中存储任意数据。可以动态地将字段添加到存储的文档中,而不需要表迁移的开销。当然,这并没有解决版本控制的问题,它仍然取决于应用程序来处理不断变化的数据结构(并不总是微不足道),但至少你不是在与数据库作斗争(基于数据库编程)。
SQL /关系数据库已经经过验证,快速且超级可靠。在某些用例中,它们更便宜,更容易。例如,对于简单的网站或博客来说,MySQL就很胜任。但即使在企业环境中,有时您也需要关系数据库强制执行的结构。如果您有一个相当静态的数据模型,并且不需要扩展到Internet互联网规模,那么SQL可能是最佳选择。
我在本教程中使用的是MongoDB,因为从一开始就轻而易举。如果你使用Spring Data MongoDB,那就更容易了!
Reactive反应式编程
Reactive是另一个很大的行话。这种感觉就像人们喜欢在派对和会议上挥之不去,只是模糊地了解它实际意味着什么。就像“存在主义”或“恩赐”一样,让我们来定义它。
如果您查看Spring WebFlux文档,它们可以非常好地概述反应意味着什么。
术语“反应性”是指围绕变化做出反应的编程模型 - 对I / O事件做出反应的网络组件,对鼠标事件做出反应的UI控制器等。从这个意义上说,非阻塞是Reactive响应式的,因为我们现在处于一种模式,即在操作完成或数据可用时对通知作出反应。 |
因此,反应/响应意味着:非阻塞,异步,并以流处理为中心。
构建Spring Boot资源服务器
从GitHub存储库克隆启动项目并检查启动分支:
git clone -b start https://github.com/oktadeveloper/okta-spring-boot-mongo-webflux-example.git |
入门项目是一个简单的Spring Boot入门项目,其中已包含必要的依赖项build.gradle。
让我们快速浏览一下依赖项:
compile('org.springframework.boot:spring-boot-starter-webflux') |
第一个是Spring WebFlux,Spring MVC的反应版本。第二个引入Spring需要的响应式MongoDB依赖项。第三个是名为Lombok的项目,它使我们在Java代码中无需键入一堆构造函数,getter和setter(您可以在他们的网页上查看项目)。最后一个依赖项是嵌入式内存中的MongoDB数据库。这个数据库非常适合测试,这样的简单教程,并且不会真正持久化。
可以使用简单的Gradle命令运行应用程序:
./gradlew bootRun
为MongoDB定义模型类
模型类:
@Document |
@Document注释是NoSQL的类似关系数据库的@Entity。它告诉Spring Boot定义了一个数据模型。在NoSQL世界中,这意味着创建文档而不是表条目。其他三个注释是自动生成getter,setter和构造函数的Lombok助手。
Kayak文档有五个属性:名称name,所有者owner,值value和类型makeModel。它们会自动映射到MongoDB的相应BSON类型。
什么是BSON类型?看一下关于这个主题的MongoDB文档。它们是用于在MongoDB文档中保留数据的二进制序列化类型。它们定义了可以存储在MongoDB数据库中的基元类型。
将ReactiveMongoRepository添加到Spring Boot App
使用@Document注释定义Kayak类告诉Spring Boot有关数据结构的信息,但实际上并没有给我们任何保存或加载数据库数据的方法。为此,您需要定义一个存储库。
这个代码非常简单:KayakRepository.java:
|
这实际上为您提供了从数据库创建,更新,读取和删除文档所需的所有基本方法。要了解如何,特别是深入研究ReactiveMongoRepository班级和各种其他超类ReactiveCrudRepository。看看该文档的ReactiveCrudRepository看到实现的方法。
ReactiveCrudRepository实际上提供了一套基本而完整的CRUD方法。ReactiveMongoRepository在此基础上构建,以提供一些特定于MongoDB的查询功能。
用Spring WebFlux实现一个Controller
添加存储库后,您就可以以编程方式操作数据。但是,我们还没有定义Web端点。必须明确定义公共Web端点KayakController.java:
@Controller |
该控制器添加两个端点:
- POST /kayaks增加了一条新的Kayak皮划艇
- GET /kayaks列出了所有的Kayak皮划艇
该类使用Spring依赖注入将KayakRepository实例自动装入控制器,您将看到如何使用存储库持久化Kayak域类。
(与传统控制器区别是Spring WebFlux返回Flux类型和Mono类型)
测试Spring Boot Server
此时,您拥有一个完全可操作的皮划艇REST资源服务器。在测试之前,请将以下方法添加到您的MainApplication课程中。这只是在应用程序加载时将一些测试数据注入数据库。
@Bean |
HTTPie是一个很棒的命令行实用程序,可以轻松地对资源服务器运行请求。如果您没有安装HTTPie,请使用安装它brew install httpie。或者前往他们的网站并实现目标。
确保您的Spring Boot应用程序正在运行。如果不是,请使用它
./gradlew bootRun。
对资源服务器运行GET请求:http :8080/kayaks这是简写
http GET http://localhost:8080/kayaks。
你会得到这个:
HTTP/1.1 200 OK |
现在尝试POST一条新的皮划艇到服务器。
http POST :8080/kayaks name="sea2" owner="Andrew" value="500" makeModel="P&H"
你应该看到:
HTTP/1.1 200 OK |