当前位置: 首页 > 科技观察

用WebFlux写一个CURD是什么体验?

时间:2023-03-20 18:09:23 科技观察

WebFlux最受诟病的就是对数据库的支持。毕竟,数据是应用程序的生命。我们接触到的应用大多都有数据库,而WebFlux在这方面的支持一直比较薄弱。这就是为什么人们总是抱怨它。不过从Spring5开始,这个问题得到了一定程度的缓解。Spring在Spring5正式发布响应式Web框架SpringWebFlux后,迫切需要一个能够满足异步响应的数据库交互API。然而,由于缺乏标准和驱动,Pivotal团队开始研究ReactiveRelationalDatabaseConnectivity,并提出了R2DBC规范API,用于评估可行性并讨论数据库供应商是否有兴趣支持一种反应式异步非阻塞驱动.一开始只有PostgreSQL、H2、MSSQL这三个数据库厂商,现在MySQL也加入进来了,这是一个很大的好处。目前最新版本的R2DBC是0.9.0.RELEASE。松哥会在下一篇文章给大家演示R2DBC的用法,而今天我们先来看看WebFlux+MongoDB的用法。毕竟这是WebFlux较早支持的数据库之一,各种API也比较成熟。让我们一步一步来。1、为了创建项目方便,我们这里直接创建一个SpringBoot项目。首先创建一个SpringBoot项目,引入MongoDB依赖和WebFlux依赖,如下:注意这里我们选择的MongoDB依赖是SpringDataReactiveMongoDB,不要选错。向上。项目创建完成后,我们首先在application.properties中配置MongoDB,如下(如果对MongoDB的操作不熟悉,可以在公众号底部菜单找到松哥的MongoDB原版教程):spring.data。mongodb.port=27017spring.data.mongodb.host=127.0.0.1spring.data.mongodb.username=madminspring.data.mongodb.password=m123spring.data.mongodb.database=testspring.data.mongodb.authentication-database=一morethingforadmin,在之前的SpringBoot视频教程中,松哥也介绍了MongoDB,感兴趣的朋友点这里:SpringBoot+Vue+微人事视频教程。配置好MongoDB后,我们的准备工作就完成了。2.实体类和Dao接下来,我们需要准备一个操作实体类。以上就是JPA的基本操作。宋弟兄不再赘述。不熟悉的可以在公众号后台回复666查看SpringBoot原教程,涉及到的实体类如下:@DocumentpublicclassUser{@IdprivateStringid;私有字符串用户名;私有字符串地址;publicStringgetId(){返回id;}publicvoidsetId(Stringid){这个.id=id;}publicStringgetUsername(){返回用户名;}publicvoidsetUsername(Stringusername){this.username=username;}publicStringgetAddress(){返回地址;}publicvoidsetAddress(Stringaddress){this.address=address;}}接下来我们提供实体类操作的接口,如下:@EnableMongoRepositoriespublicinterfaceUserDaoextendsReactiveMongoRepository{}自定义一个继承自ReactiveMongoRepository的空接口,里面什么都不写,这个套路就是和之前宋哥视频介绍过的JPA的用法一样(毕竟是SpringData家族的),这个没什么好说的,不再赘述。3.测试界面接下来我们来看一下测试界面。3.1添加首先让我们看看添加数据。@RestController@RequestMapping("/user")公共类UserController{@AutowiredUserDaouserDao;@PostMapping("/")publicMonoaddUser(@RequestBodyUseruser){returnuserDao.save(user);}}Add完成后,返回刚刚添加成功的对象。save方法的返回值为Mono。看一下测试结果:3.2查询先看一下查询结果:@GetMapping("/")publicFluxgetAll(){returnuserDao.findAll();}@GetMapping(value="/stream/all",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFluxstreamGetAll(){returnuserDao.findAll();}我们提供了两种查询接口,一种是返回包含多个对象的Flux,另一种是我设置了一个responseContent-Type是text/event-stream,通过responsivestream返回数据。详见【服务器推送数据,除了WebSocket你还能想到什么?】一篇。我们来看一下查询效果:可以看到两种不同的查询方式返回的数据格式也是不一样的。前者以数组的形式返回一次数据,后者以SSE的形式返回多次数据。3.3删除让我们再看看删除。按照RESTful规范,如果删除成功,响应码为200,如果删除失败,响应码为404。因此,我们开发的接口如下:@DeleteMapping("/{id}")publicMono>deleteUser(@PathVariableStringid){returnuserDao.findById(id).flatMap(user->userDao.delete(user).then(Mono.just(newResponseEntity(HttpStatus.OK)))).defaultIfEmpty(newResponseEntity(HttpStatus.NOT_FOUND));}先从数据库中查询相关数据,然后调用flatMap,删除flatMap中的数据,删除完成后,给出一个200的响应码,如果查询时没有查询到数据时,给出404响应码。可以看到,删除成功后,响应码为200;删除失败后响应码为404:3.4修改再看修改,和之前的删除类似,先查询再修改:@PutMapping("/")publicMono>updateUser(@RequestBody用户user){returnuserDao.findById(user.getId()).flatMap(u->userDao.save(user)).map(u->newResponseEntity(u,HttpStatus.OK)).defaultIfEmpty(newResponseEntity(HttpStatus.NOT_FOUND));}如果修改的数据不存在,会给出404响应:3.5自定义查询方法松哥之前SpringDataJpa的一些查询API这里也适用(后台回复666公众号获取上期教程)。比如我们可以在UserDao中自定义一个查询方法:@EnableMongoRepositoriespublicinterfaceUserDaoextendsReactiveMongoRepository{FluxfindUserByUsernameContaining(Stringname);}然后添加一个接口调用这个方法:@GetMapping("/byname")publicFluxgetUserByName(Stringname){returnuserDao.findUserByUsernameContaining(name);}这样这个接口就可以查询到所有名字中包含某个关键字的用户。JPA的其他用法在这里都是适用的,因为在之前的文章中已经讲过了,这里就不赘述了。4.总结好了,今天我们使用WebFlux来写一个简单的CURD。先来体验一下WebFlux的基本使用。下一篇宋哥将和大家分享WebFlux是如何连接关系型数据库的。敬请关注。