今天我们继续来搞WebFlux! WebFlux最为人所诟病的是数据库的支持问题,毕竟数据是一个应用的生命,我们接触的大部分应用程序都是有数据库的,而WebFlux在这一方面的支持行一直比较弱,这也是大家总是吐槽它的原因。 不过从Spring5开始,这一问题得到了一定程度的缓解。 Spring官方在Spring5发布了响应式Web框架SpringWebFlux之后急需能够满足异步响应的数据库交互API,不过由于缺乏标准和驱动,Pivotal团队开始自己研究响应式关系型数据库连接ReactiveRelationalDatabaseConnectivity,并提出了R2DBC规范API用来评估可行性并讨论数据库厂商是否有兴趣支持响应式的异步非阻塞驱动程序。最早只有PostgreSQL、H2、MSSQL三家数据库厂商,不过现在MySQL也加入进来了,这是一个极大的利好。目前R2DBC的最新版本是0。9。0。RELEASE。 松哥在接下来的文章中将会和大家演示R2DBC的用法,但是今天我们还是先来看看WebFluxMongoDB的用法,毕竟这是WebFlux较早支持的数据库之一,各种API都比较成熟,我们一步一步来。1。项目创建 方便起见,我们这里就直接创建SpringBoot项目,首先创建一个SpringBoot项目,引入MongoDB依赖和WebFlux依赖,如下: 注意我们这里选择的MongoDB依赖是SpringDataReactiveMongoDB,千万别选错了。 项目创建完成后,我们先在application。properties中对MongoDB进行简单配置,如下(如果小伙伴们尚不熟悉MongoDB的操作,可以在公众号底部菜单找到松哥原创的MongoDB教程):spring。data。mongodb。port27017spring。data。mongodb。host127。0。0。1spring。data。mongodb。usernamemadminspring。data。mongodb。passwordm123spring。data。mongodb。databasetestspring。data。mongodb。authenticationdatabaseadmin 多说一句,在之前的SpringBoot视频教程中,松哥对MongoDB也有过介绍,感兴趣的小伙伴戳这里:SpringBootVue微人事视频教程。 配置完MongoDB后,我们的准备工作就算完成了。2。实体类与Dao 接下来我们需要准备一个操作的实体类,这些都是JPA的基本操作,松哥就不再赘述,如果小伙伴们不熟悉的话,可以公号后台回复666查看原创的SpringBoot教程,里边有涉及到,实体类如下:DocumentpublicclassUser{IdprivateStringid;privateStringusername;privateStringaddress;publicStringgetId(){returnid;}publicvoidsetId(Stringid){this。idid;}publicStringgetUsername(){returnusername;}publicvoidsetUsername(Stringusername){this。usernameusername;}publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){this。addressaddress;}} 接下来我们再提供一个实体类操作的接口,如下:EnableMongoRepositoriespublicinterfaceUserDaoextendsReactiveMongoRepositoryUser,String{} 自定义一个空的接口继承自ReactiveMongoRepository,里边什么都不用写,这套路就和松哥之前视频中介绍的JPA的用法如出一辙(毕竟都是SpringData家族),所以这块就没啥好说的,不赘述。3。测试接口 接下来我们来看看测试接口。3。1添加 首先我们来看看添加数据。RestControllerRequestMapping(user)publicclassUserController{AutowiredUserDaouserDao;PostMapping()publicMonoUseraddUser(RequestBodyUseruser){returnuserDao。save(user);}} 添加完成后,返回刚刚添加成功的对象。save方法的返回值就是Mono。 我们来看看测试效果: 3。2查询 再来看看查询效果:GetMapping()publicFluxUsergetAll(){returnuserDao。findAll();}GetMapping(valuestreamall,producesMediaType。TEXTEVENTSTREAMVALUE)publicFluxUserstreamGetAll(){returnuserDao。findAll();} 我们提供了两个查询接口,一个就是返回Flux,里边包含多个对象,还有一个我设置了响应的ContentType为texteventstream,通过响应式流返回数据,具体参见【服务端推送数据,除了WebSocket你还能想到啥?】一文。 我们来看看查询效果: 可以看到两种不同的查询方式返回的数据格式也有差异。前者是以数组形式一次性返回数据,后者是以SSE的形式多次返回数据。3。3删除 再来看看删除。 按照RESTful规范,如果删除成功请求响应码就是200,如果删除失败请求响应码就是404,因此,我们开发出来的接口如下:DeleteMapping({id})publicMonoResponseEntityVoiddeleteUser(PathVariableStringid){returnuserDao。findById(id)。flatMap(useruserDao。delete(user)。then(Mono。just(newResponseEntityVoid(HttpStatus。OK))))。defaultIfEmpty(newResponseEntity(HttpStatus。NOTFOUND));} 首先从数据库中查询出相关的数据,然后调用flatMap,在flatMap中对数据进行删除处理,删除完成后,给出一个200的响应码,如果查询的时候没有查询到数据,就给一个404响应码。 可以看到,删除成功后,响应码为200: 删除失败后,响应码为404: 3。4修改 再来看看修改,和前面的删除类似,先查询,再修改:PutMapping()publicMonoResponseEntityUserupdateUser(RequestBodyUseruser){returnuserDao。findById(user。getId())。flatMap(uuserDao。save(user))。map(unewResponseEntityUser(u,HttpStatus。OK))。defaultIfEmpty(newResponseEntity(HttpStatus。NOTFOUND));} 如果修改的数据不存在的话,就会给出一个404响应: 3。5自定义查询方法 松哥之前的SpringDataJpa中讲的一些查询API,这里同样是适用的(公号后台回复666获取之前的教程)。 例如我们可以在UserDao中自定义一个查询方法:EnableMongoRepositoriespublicinterfaceUserDaoextendsReactiveMongoRepositoryUser,String{FluxUserfindUserByUsernameContaining(Stringname);} 然后添加一个接口调用该方法:GetMapping(byname)publicFluxUsergetUserByName(Stringname){returnuserDao。findUserByUsernameContaining(name);} 这样该接口就可以查询名字中包含某关键字的所有用户了。 其他关于JPA的用法这里都是适用的,因为在之前的文章中讲过,松哥这里就不再赘述了。4。小结 好啦,今天我们就用WebFlux写了一个简单的CURD,大家先来感受下WebFlux的基本用法,后面的文章将和大家分享WebFlux如何连接关系型数据库,敬请期待。 原文链接:https:mp。weixin。qq。comsKUDS8ss6BRIkMWwjCeYg