为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。
本章节为【学成在线】项目的 day04
的内容
freemarker
框架实现页面静态化以及发布一、页面静态化需求
cms
系统的功能就是根据运营的需要,对门户等子系统的部分页面进行管理,从而实现快速的根据用户需求修改页面的内容并上线需求。
html
以及 js
文件, cms
系统是通过程序自动化的对页面的内容进行修改,通过页面静态化技术生成 html
页面。
模板
+ 数据
,在添加页面的时候我们选择了页面的模板。
html
页面存放在文件系统中
html
页面发布到服务器
freemarker
并不关心数据的来源,只是根据模板的内容,将数据模型在模板中显示并输出具体的(通常为 html
,也可以生成其他格式的文件)
java
中可以是基本类型也可以是 List、Map、Pojo 等复杂类型
我们在原有的工程下,创建一个test-freemarker
的 maven
模块,测试工程专门用于freemarker的功能测试与模板的测试。
[摘要] 不需掏钥匙或业主卡,点一点手机就能过门禁;家里水管漏水时,足不出户就能报事报修,还能全程跟踪维修进度,给工程师傅打个好评;想知道附近哪家火锅好吃,迁户口需要准备哪些材料,打个400电话就能得到满意解答
不需掏钥匙或业主卡,点一点手机就能过门禁;家里水管漏水时,足不出户就能报事报修,还能全程跟踪维修进度,给工程师傅打个好评;想知道附近哪家火锅好吃,迁户口需要准备哪些材料,打个
如此便捷生活的背后,是龙湖智慧服务研发应用多年的全套智慧社区系统平台。中国物业管理协会会长沈建忠曾表示,物业行业分享新技术革命红利的时代已经来到。在龙湖对外接项目进行品质升级的过程中,输入科技系统、进行“智慧升级”是必不可少的一环。
设施设备的管理水平直接影响一个社区的安全和生活品质。龙湖智慧服务总经理曾益明曾说:“今天的龙湖智慧服务已经把所有的设施设备都纳入物联网管理平台。每一台设施设备,都可以通过物联网集成到后台智能化管理。”
以龙湖智慧服务自主研发的RBA(远程楼宇自控系统)为例,在进行设备房环境、消防、供配电等运行数据实时监测的同时,物业工程师在手机端即可进行报事和自主接单,确保故障时间得到响应和处理。
此外,随着“慧眼”系统的逐步接入,外接项目园区品质管控也逐渐纳入龙湖统一品检平台,坐在龙湖集成指挥中心的品检专家,可以在电脑或者手机端随时清晰查看任何一个项目的现场运营品质,实现集中、即时、高效的标准化管理。
在龙湖接管的重庆万州茶庄印象、成都汉安天地、上海慧芝湖等等多个社区,持续推进智慧化建设,先后引入业主APP、智能车管、自助缴费机等,便捷业主生活的同时,完成FM&RBA系统、慧眼系统的搭建,实现了园区设施设备的智能化管理。
免责声明:凡注明“来源:房天下”的所有文字图片等资料,版权均属房天下所有,转载请注明出处;文章内容仅供参考,不构成投资建议,也不代表房天下赞同其观点。文中所涉面积,如无特殊说明,均为建筑面积。文中出现的图片仅供参考,以售楼处实际情况为准。
Spring提供了完整的支持响应式的服务端技术栈。
由此看来,Spring WebFlux与Vert.x有一些相通之处,都是建立在非阻塞的异步I/O和事件驱动的基础之上的。
2)响应式Http客户端
此外,Spring WebFlux也提供了一个响应式的Http客户端API WebClient
。它可以用函数式的方式异步非阻塞地发起Http请求并处理响应。其底层也是由Netty提供的异步支持。
我们可以把WebClient
看做是响应式的RestTemplate
,与后者相比,前者:
简单介绍这些,让我们来Coding吧~
本节,我们通过以下几个例子来逐步深入地了解它的使用方法:
** 1. 先介绍一下使用Spring WebMVC风格的基于注解的方式如何编写响应式的Web服务,这几乎没有学习成本,非常赞。虽然这种方式在开发上与Spring WebMVC变化不大,但是框架底层已经是完全的响应式技术栈了;
WebClient
与前几步做好的服务端进行通信;
Spring Boot 2是基于Spring 5的,其中一个比较大的更新就在于支持包括spring-webflux和响应式的spring-data在内的响应式模块。Spring Boot 2即将发布正式版,不过目前的版本从功能上已经完备,下边的例子我们就用Spring Boot 2在进行搭建。
我们首先用Spring WebMVC开发一个只有Controller层的简单的Web服务,然后仅仅做一点点调整就可切换为基于Spring WebFlux的具有同样功能的Web服务。
以下截图来自IntelliJ IDEA,不过其他IDE也都是类似的。
创建后的项目POM中,包含下边的依赖,即表示基于Spring WebMVC:
使用IDE启动应用,或使用maven命令:
通过打印的log可以看到,服务运行于Tomcat的8080端口:
基于Spring WebFlux的项目与上边的步骤一致,仅有两点不同。我们这次偷个懒,就不从新建项目了,修改一下上边的项目:
5)Controller中处理请求的返回类型采用响应式类型
仅需要上边两步就改完了,是不是很简单,同样的方法启动应用。启动后发现应用运行于Netty上:
从上边这个非常非常简单的例子中可以看出,Spring真是用心良苦,WebFlux提供了与之前WebMVC相同的一套注解来定义请求的处理,使得Spring使用者迁移到响应式开发方式的过程变得异常轻松。
虽然我们只修改了少量的代码,但是其实这个简单的项目已经脱胎换骨了。整个技术栈从命令式的、同步阻塞的【spring-webmvc + servlet + Tomcat】变成了响应式的、异步非阻塞的【spring-webflux + Reactor + Netty】。
Netty是一套异步的、事件驱动的网络应用程序框架和工具,能够开发高性能、高可靠性的网络服务器和客户端程序,因此与同样是异步的、事件驱动的响应式编程范式一拍即合。
下边的内容了解即可,就不实战了。
既然是响应式编程了,有些朋友可能会想统一用函数式的编程风格,WebFlux满足你。WebFlux提供了一套函数式接口,可以用来实现类似MVC的效果。我们先接触两个常用的。
再回头瞧一眼上边例子中我们用Controller
定义定义对Request的处理逻辑的方式,主要有两个点:
@RequestMapping
注解定义好这个方法对什么样url进行响应。
下面我们用函数式的方式开发两个Endpoint:
/time
返回当前的时间;
/date
返回当前的日期。
不过这么写在业务逻辑复杂的时候不太好组织,我们通常采用跟MVC类似的代码组织方式,将同类业务的HandlerFunction放在一个类中,然后在Java Config中将RouterFunction配置为Spring容器的Bean。我们继续在第一个例子的代码上开发:
1)创建统一存放处理时间的Handler类
由于出现次数通常比较多,这里静态引入
ServerResponse.ok()
方法。
我们可能会遇到一些需要网页与服务器端保持连接(起码看上去是保持连接)的需求,比如类似微信网页版的聊天类应用,比如需要频繁更新页面数据的监控系统页面或股票看盘页面。我们通常采用如下几种技术:
既然响应式编程是一种基于数据流的编程范式,自然在服务器推送方面得心应手,我们基于函数式方式再增加一个Endpoint /times
,可以每秒推送一次时间。
重启服务后,测试一下:
就酱,访问这个url会收到持续不断的报时数据(时间数据是在data
中的)。
那么用注解的方式如何进行服务端推送呢,这个演示就融到下一个例子中吧~
开发基于响应式流的应用,就像是在搭建数据流流动的管道,从而异步的数据能够顺畅流过每个环节。前边的例子主要聚焦于应用层,然而绝大多数系统免不了要与数据库进行交互,所以我们也需要响应式的持久层API和支持异步的数据库驱动。就像从自来水厂到家里水龙头这个管道中,如果任何一个环节发生了阻塞,那就可能造成整体吞吐量的下降。
我们这个例子很简单,就是关于User
的增删改查,以及基于注解的服务端推送。
既然是举例,我们随便定义几个属性吧~
然后为User
添加注解:
我们可以利用IDE看一下生成的方法(如下图黄框所示):
可能需要先在IDE中进行少量配置以便支持lombok的注解,比如IntelliJ IDEA:
- 开启对注解编译的支持:
lombok对于Java开发者来说绝对算是个福音了,希望使用Kotlin的朋友不要笑话我们土哦~
OK,这样我们的模型就准备好了。MongoDB会自动创建collection,默认为类名首字母小写,也就是user
。
Spring Boot为我们搞定了几乎所有的,太赞了,下边是MongoDB的默认配置:
ReactiveCrudRepository
已经提供了基本的增删改查的方法,根据业务需要,我们增加四个方法(在此膜拜一下Spring团队的牛人们,使得我们仅需按照规则定义接口方法名即可完成DAO层逻辑的开发,牛~)
由于业务逻辑几乎为零,只是简单调用了DAO层,直接贴代码:
* 如果传入的user没有id属性,由于username是unique的,在重复的情况下有可能报错, * 这时找到以保存的user记录用传入的user更新它。如图,增加操作是成功的,只要username不变,再次发送请求会更新该记录。
图中birthday的时间差8小时,不去管它。
用同样的方法增加一个李四,之后我们再来测试一下查询。
看到这里细心的朋友可能会有点嘀咕,怎么看是不是异步的呢?毕竟查询全部的时候,结果都用中括号括起来了,这和原来返回List<User>
的效果似乎没多大区别。假设一下查询100个数据,如果是异步的话,以我们对“异步响应式流”的印象似乎应该是一个一个至少是一批一批的到达客户端的嘛。我们加个延迟验证一下:
每个元素都延迟1秒,现在我们在数据库里弄三条记录,然后请求查询全部的那个URL,发现并不是像/times
一样一秒一个地出来,而是3秒之后一块儿出来的。果然如此,这一点都不响应式啊!
重启服务再次请求,发现三个user是一秒一个的速度出来的,中括号也没有了,而是一个一个独立的JSON值构成的json stream:
对于稍微复杂的业务逻辑或一些必要的异常处理,比如上边的save方法,请一定采用响应式的编程方式来定义,从而一切都是异步非阻塞的。如下图所示,从HttpServer(如Netty或Servlet3.1以上的Servlet容器)到ServerAdapter(Spring WebFlux框架提供的针对不同server的适配器),到我们编写的Controller和DAO,以及异步数据库驱动,构成了一个完整的异步非阻塞的管道,里边流动的就是响应式流。
下面,我们用WebClient测试一下前边几个例子的成果。
CountDownLatch
。
为了多演示一些不同的实现方式,下边的例子我们调整几个地方,但是效果跟上边是一样的:
blockLast
方法,顾名思义,在收到最后一个元素前会阻塞,响应式业务场景中慎用。
/times
是一个无限流,这里取前10个,会导致流被取消;
许多朋友看到这个题目会想到Websocket,的确,Websocket确实可以实现全双工通信,但它的数据传输并非是完全基于HTTP协议的,关于Websocket我们后边再聊。
下面我们实现一个这样两个Endpoint:
/events
,“源源不断”地收集数据,并存入数据库;
/events
,“源源不断”将数据库中的记录发出来。
Mono<Void>
作为方法返回值,表示如果传输完的话只给一个“完成信号”就OK了;
准备到此为止,类如下。我们来完成上边的两个TODO吧。
在服务端,WebFlux也支持接收一个数据流作为请求参数,从而实现一个接收数据流的Endpoint。
insert
返回的是保存成功的记录的Flux,但我们不需要,使用then
方法表示“忽略数据元素,只返回一个完成信号”。
服务端写好后,启动之,再看一下客户端怎么写(还是放在src/test
下):
take
的话表示无限个元素的数据流;
body
方法设置请求体的数据。
运行一下这个测试,根据控制台数据可以看到是一条一条将数据发到/events
的,看一下MongoDB中的数据:
回想一下前边/user
的例子,当数据库中所有的内容都查询出来之后,这个流就结束了,因为其后跟了一个“完成信号”,我们可以通过在UserService
的findAll()
方法的流上增加log()
操作符来观察更详细的日志:
我们可以看到在三个onNext
信号后是一个onComplete
信号。
这样的流是有限流,这个时候如果在数据库中再新增一个User的话,已经结束的请求也不会再有新的内容出现了。
反观/times
请求,它会无限地发出SSE,而不会有“完成信号”出现,这是无限流。
我们希望的情况是无论是请求GET的/events
之后,当所有数据都发完之后,不要结束,而是挂起等待新的数据。如果我们用上边的POST的/events
传入新的数据到数据库后,新的数据会自动地流到客户端。
这可以在DAO层配置实现:
@Tailable
注解的作用类似于linux的tail
命令,被注解的方法将发送无限流,需要注解在返回值为Flux这样的多个元素的Publisher的方法上;
WebFluxDemoApplication
了;
OK,这个时候我们请求一下http://localhost:8080/events
,发现立马返回了,并没有挂起。原因在于collection中一条记录都没有,而@Tailable
起作用的前提是至少有一条记录。
跑一下WebClient测试程序插入5条数据,然后再次请求:
请求是挂起的,这没错,但是只有两条数据,看WebClient测试程序的控制台明明发出了5个请求啊。
maxDocuments
限制了记录条数,size
限制容量且是必须定义的,因为MongoDB不像关系型数据库有严格的列和字段大小定义,鬼知道会存多大的数据进来,所以容量限制是必要的。
好了,再次启动应用,先插入5条数据,然后请求/events
,收到5条记录后请求仍然挂起,在插入5条数据,curl客户端又会陆续收到新的数据。
我们用代码搭建了图中箭头所表示的“管道”,看效果还是很畅通的嘛。现在再回想我们最初的那个Excel的例子,是不是感觉这个demo很有响应式的“范儿”了呢?
这一节,我们对WebFlux做了一个简单的基于实例的介绍,相信你对响应式编程及其在WEB应用中如何发挥作用有了更多的体会,本章的实战是比较基础的,初衷是希望能够通过上手编写代码体会响应式编程的感觉,因为切换到响应式思维方式并非易事。
这一章的核心关键词其实翻来覆去就是:“异步非阻塞的响应式流”。我们了解了异步非阻塞的好处,也知道如何让数据流动起来,下面我们就通过对实例的性能测试,借助实实在在的数据,真切感受一下异步非阻塞的“丝滑”。