WebFlux拨云见日之前端整合,你悟了吗?

前言

从spring5中加入webflux的消息现世已经有一段时间了,也发现了一些朋友的公司在使用webfux,但是大多数都是用作为服务器之间的一些通讯、路由控制来使用,然而真正的把他当着一个web服务来提供给前端API的并木有。早年我就接触了bigpipe的概率了,但是在java的领域并不怎么活,单流的数据响应是否好像类似呢?于是我就研究了webflux和前端整合分享一下大家共同探讨...

哦对了,我这里有一套Web前端从入门到精通的全套资料,价值4980元,现免费送给大家,但是要加我的Web前端学习Q群:983840410才可以免费领取,因为我在里面会私发给大家,欢迎你前来领取,

WebFlux

WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好.

实战效果展示

WebFlux拨云见日之前端整合,你悟了吗?_第1张图片

第一处:

是对推送SSE API允许网页获得来自服务器的更新(HTML5),用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。服务器响应的MIME类型必须是text/event-stream,而且是浏览器中的JavaScript API 能解析格式输出。SSE 支持短轮询、长轮询和HTTP 流,而且能在断开连接时自动确定何时重新连接。

java代码:

@RestController@RequestMapping("/sse")publicclassSseController{privateint count_down_sec=3*60*60;@GetMapping(value="/countDown",produces = MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux> countDown() {returnFlux.interval(Duration.ofSeconds(1)).map(seq -> Tuples.of(seq, getCountDownSec())).map(data-> ServerSentEvent.builder().event("countDown").id(Long.toString(data.getT1())).data(data.getT2().toString()).build());}privateString getCountDownSec() {if(count_down_sec>0) {int h = count_down_sec/(60*60);int m = (count_down_sec%(60*60))/60;int s = (count_down_sec%(60*60))%60;count_down_sec--;return"活动倒计时:"+h+" 小时 "+m+" 分钟 "+s+" 秒";}return"活动倒计时:0 小时 0 分钟 0 秒";}}

HTML代码:

//js代码//记录加载次数vartime=1;if(typeof(EventSource) !=="undefined") {varsource =newEventSource("/sse/countDown");console.log(source);source.addEventListener("countDown",function(e){document.getElementById("result").innerHTML = e.data;},false);//使用false表示在冒泡阶段处理事件,而不是捕获阶段。}else{document.getElementById("result").innerHTML ="抱歉,你的浏览器不支持 server-sent 事件...";}//html代码

webflux中的sse并不是什么新的东西,在之前都有出现过,就不多介绍了。

第二三处就是对webflux中的Flux接口信息

java代码(主要是针对Mongo)

Entity:

@Data@EqualsAndHashCode(callSuper=false)publicclassCommodityextendsParentEntityimplementsSerializable{privatestaticfinallong serialVersionUID =6659341305838439447L;/**

* 店铺ID

*/privateLongshopId;/**

* 商品名

*/@NotNull(message ="商品名不能为空")@Pattern(regexp ="^.{0,50}$",message ="商品名必须是小于50位字符串")privateStringname;/**

* 商品详情

*/@Pattern(regexp ="^.{0,500}$",message ="商品详情必须是小于500位字符串")privateStringdetails;/**

* 商品图片地址

*/privateStringimageUrl;/**

* 商品图片地址

*/privateIntegertype;/**

* 商品单价

*/@Min(value =0)privateBigDecimalprice;/**

* 商品库存

*/@Min(value =0)privateIntegerpcs;}

Entity的父类:

publicclassParentEntity{/**

* 商品ID

*/publicLongid;publicLonggetId() {returnid;}publicvoid setId(Longid) {this.id = id;}}

DAO:

importorg.springframework.data.mongodb.repository.ReactiveMongoRepository;importcom.flying.cattle.wf.entity.Commodity;publicinterfaceCommodityRepositoryextendsReactiveMongoRepository{}

SERVICE:

importcom.flying.cattle.wf.aid.IService;importcom.flying.cattle.wf.entity.Commodity;publicinterfaceCommodityServiceextendsIService{}

SERVICE的父类:

import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;/** *

* 顶级 Service *

* * @author BianPeng * @since 2019/6/17 */public interface IService{/**    *

* 插入一条记录(选择字段,策略插入)    *

*    * @param entity 实体对象    */Monoinsert(T entity);        /**    *

* 根据 ID 删除    *

* @param id 主键ID    */MonodeleteById(Long id);        /**    *

* 根据 ID 删除    *

* @param id 主键ID    */Monodelete(T entity);        /**    *

* 根据 ID 选择修改    *

* @param entity 实体对象    */MonoupdateById(T entity);        /**    *

* 根据 ID 查询    *

* @param id 主键ID    */MonofindById(Long id);    /**    *

* 查询所有    *

*/FluxfindAll();}

SERVICE-IMPL

importorg.springframework.stereotype.Service;importcom.flying.cattle.wf.aid.ServiceImpl;importcom.flying.cattle.wf.dao.CommodityRepository;importcom.flying.cattle.wf.entity.Commodity;importcom.flying.cattle.wf.service.CommodityService;@Servicepublic class CommodityServiceImpl extends ServiceImpl implements CommodityService {}

SERVICE-IMPL 父类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.mongodb.repository.ReactiveMongoRepository;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;/** *

* IService 实现类( 泛型:M 是 mapper 对象,T 是实体 , PK 是主键泛型 ) *

* *@authorBianPeng *@since2019/6/17 */publicclassServiceImpl,T> implements IService{@AutowiredprotectedM baseDao;@OverridepublicMono insert(T entity) {returnbaseDao.save(entity);}@OverridepublicMono deleteById(Longid) {// TODO Auto-generated method stubbaseDao.deleteById(id);returnMono.create(entityMonoSink -> entityMonoSink.success());}@OverridepublicMono delete(T entity) {// TODO Auto-generated method stubbaseDao.delete(entity);returnMono.create(entityMonoSink -> entityMonoSink.success());}@OverridepublicMono updateById(T entity) {// TODO Auto-generated method stubreturnbaseDao.save(entity);}@OverridepublicMono findById(Longid) {// TODO Auto-generated method stubreturnbaseDao.findById(id);}@OverridepublicFlux findAll() {// TODO Auto-generated method stubreturnbaseDao.findAll();}}

CONTROLLER:

importjava.math.BigDecimal;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importcom.flying.cattle.wf.aid.AbstractController;importcom.flying.cattle.wf.entity.Commodity;importcom.flying.cattle.wf.service.CommodityService;importcom.flying.cattle.wf.utils.ValidationResult;importcom.flying.cattle.wf.utils.ValidationUtils;importreactor.core.publisher.Mono;@RestController@RequestMapping("/commodity")publicclassCommodityControllerextendsAbstractController{Loggerlogger =LoggerFactory.getLogger(this.getClass());@GetMapping("/add")publicMono add()throwsException{Commodityobj =newCommodity();Longid=super.getAutoIncrementId(obj);obj.setId(id);obj.setShopId(1l);obj.setName("第"+ id +"个商品");obj.setDetails("流式商品展示");obj.setImageUrl("/aa/aa.png");obj.setPcs(1);obj.setPrice(newBigDecimal(998));obj.setType(1);ValidationResultvr =ValidationUtils.validateEntity(obj);if(!vr.isHasErrors()) {returnbaseService.insert(obj);}else{thrownewException(vr.getFirstErrors());}}}

CONTROLLER父类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PathVariable;importorg.springframework.web.bind.annotation.PostMapping;importcom.flying.cattle.wf.entity.ParentEntity;importcom.flying.cattle.wf.service.impl.RedisGenerateId;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;/**    *

自动生成工具:mybatis-dsc-generator

*  *

说明: 资金归集API接口层

*@version: V1.0 *@author: BianPeng * */publicclassAbstractController,T extends ParentEntity>{@AutowiredprivateRedisGenerateId redisGenerateId;@AutowiredprotectedS baseService;@GetMapping("/getId")publicLonggetAutoIncrementId(T entity){returnredisGenerateId.generate(entity.getClass().getName());}@PostMapping("/save")publicMono save(T entity) {entity.setId(getAutoIncrementId(entity));returnbaseService.insert(entity);}@PostMapping("/deleteById")publicMono deleteById(Longid) {// TODO Auto-generated method stubreturnbaseService.deleteById(id);}@PostMapping("/delete")publicMono delete(T entity) {// TODO Auto-generated method stubreturnbaseService.delete(entity);}@PostMapping("/updateById")publicMono updateById(T entity) {// TODO Auto-generated method stubreturnbaseService.updateById(entity);}@GetMapping("/getById/{id}")publicMono findById(@PathVariable("id")Longid) {// TODO Auto-generated method stubreturnbaseService.findById(id);}@GetMapping(value="/findAll",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)publicFlux findAll() {// TODO Auto-generated method stubreturnbaseService.findAll();}}

HTML代码:

商品展示//记录加载次数vartime=1;if(typeof(EventSource) !=="undefined") {varsource =newEventSource("/sse/countDown");console.log(source);source.addEventListener("countDown",function(e){document.getElementById("result").innerHTML = e.data;},false);//使用false表示在冒泡阶段处理事件,而不是捕获阶段。}else{document.getElementById("result").innerHTML ="抱歉,你的浏览器不支持 server-sent 事件...";}/************************以上是SSE的JS************************/$(function(){varxhr =newXMLHttpRequest();xhr.open('GET','/commodity/findAll');xhr.send(null);//发送请求xhr.onreadystatechange =function(){//2是空响应,3是响应一部分,4是响应完成if(xhr.readyState >2) {//这儿可以使用response与responseText,因为我接口返回的就是String数据,所以选择responseTextvarnewData = xhr.response.substr(xhr.seenBytes);newData = newData.replace(/\n/g,"#");newData = newData.substring(0, newData.length -1);vardata = newData.split("#");//显示加载次数,和大小$("#dataModule").append("第"+time+"次数据响应"+data.length+"条          ");$("#note").append("

第"+time+"次数据响应"+data.length+"条
");varhtml="";for(vari =0; i

前端的代码就这个样子,展示出来的数据就是开始那张图,数据反应多少条前端马上就展示数据,不需要等待接口反应完成并接收完所以数据才展示数据。现在webflux的使用其实还并不是太普及,很多东西都得需要我自己去挖掘,有兴趣的朋友可以加群:340697945大家一起交流,相互学习。

你可能感兴趣的:(WebFlux拨云见日之前端整合,你悟了吗?)