用 WebFlux 写个 CURD 是什么体验?

TienChin 视频杀青啦~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦

Spring 源码分析视频教程连载中,感兴趣的小伙伴戳这里:Spring源码应该怎么学?

今天我们继续来搞 WebFlux!

WebFlux 最为人所诟病的是数据库的支持问题,毕竟数据是一个应用的生命,我们接触的大部分应用程序都是有数据库的,而 WebFlux 在这一方面的支持行一直比较弱,这也是大家总是吐槽它的原因。

不过从 Spring5 开始,这一问题得到了一定程度的缓解。

Spring 官方在 Spring5 发布了响应式 Web 框架 Spring WebFlux 之后急需能够满足异步响应的数据库交互 API,不过由于缺乏标准和驱动,Pivotal 团队开始自己研究响应式关系型数据库连接 Reactive Relational Database Connectivity,并提出了 R2DBC 规范 API 用来评估可行性并讨论数据库厂商是否有兴趣支持响应式的异步非阻塞驱动程序。最早只有 PostgreSQL 、H2、MSSQL 三家数据库厂商,不过现在 MySQL 也加入进来了,这是一个极大的利好。目前 R2DBC 的最新版本是 0.9.0.RELEASE。

松哥在接下来的文章中将会和大家演示 R2DBC 的用法,但是今天我们还是先来看看 WebFlux+MongoDB 的用法,毕竟这是 WebFlux 较早支持的数据库之一,各种 API 都比较成熟,我们一步一步来。

1.项目创建

方便起见,我们这里就直接创建 Spring Boot 项目,首先创建一个 Spring Boot 项目,引入 MongoDB 依赖和 WebFlux 依赖,如下:

注意我们这里选择的 MongoDB 依赖是 Spring Data Reactive MongoDB,千万别选错了。

项目创建完成后,我们先在 application.properties 中对 MongoDB 进行简单配置,如下(如果小伙伴们尚不熟悉 MongoDB 的操作,可以在公众号底部菜单找到松哥原创的 MongoDB 教程):

spring.data.mongodb.port=27017
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.username=madmin
spring.data.mongodb.password=m123
spring.data.mongodb.database=test
spring.data.mongodb.authentication-database=admin

多说一句,在之前的 Spring Boot 视频教程中,松哥对 MongoDB 也有过介绍,感兴趣的小伙伴戳这里:Spring Boot+Vue+微人事视频教程

配置完 MongoDB 后,我们的准备工作就算完成了。

2.实体类与 Dao

接下来我们需要准备一个操作的实体类,这些都是 JPA 的基本操作,松哥就不再赘述,如果小伙伴们不熟悉的话,可以公号后台回复 666 查看原创的 Spring Boot 教程,里边有涉及到,实体类如下:

@Document
public class User {
    @Id
    private String id;
    private String username;
    private String address;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

接下来我们再提供一个实体类操作的接口,如下:

@EnableMongoRepositories
public interface UserDao extends ReactiveMongoRepository<User,String{
}

自定义一个空的接口继承自 ReactiveMongoRepository,里边什么都不用写,这套路就和松哥之前视频中介绍的 JPA 的用法如出一辙(毕竟都是 Spring Data 家族),所以这块就没啥好说的,不赘述。

3.测试接口

接下来我们来看看测试接口。

3.1 添加

首先我们来看看添加数据。

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserDao userDao;

    @PostMapping("/")
    public Mono<User> addUser(@RequestBody User user) {
        return userDao.save(user);
    }
}

添加完成后,返回刚刚添加成功的对象。save 方法的返回值就是 Mono。

我们来看看测试效果:

3.2 查询

再来看看查询效果:

@GetMapping("/")
public Flux<User> getAll() {
    return userDao.findAll();
}
@GetMapping(value = "/stream/all", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<User> streamGetAll() {
    return userDao.findAll();
}

我们提供了两个查询接口,一个就是返回 Flux,里边包含多个对象,还有一个我设置了响应的 Content-Type 为 text/event-stream,通过响应式流返回数据,具体参见【服务端推送数据,除了 WebSocket 你还能想到啥?】一文。

我们来看看查询效果:

可以看到两种不同的查询方式返回的数据格式也有差异。前者是以数组形式一次性返回数据,后者是以 SSE 的形式多次返回数据。

3.3 删除

再来看看删除。

按照 RESTful 规范,如果删除成功请求响应码就是 200,如果删除失败请求响应码就是 404,因此,我们开发出来的接口如下:

@DeleteMapping("/{id}")
public Mono<ResponseEntity<Void>> deleteUser(@PathVariable String id) {
    return userDao.findById(id)
            .flatMap(user -> userDao.delete(user).then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK))))
            .defaultIfEmpty(new ResponseEntity(HttpStatus.NOT_FOUND));
}

首先从数据库中查询出相关的数据,然后调用 flatMap,在 flatMap 中对数据进行删除处理,删除完成后,给出一个 200 的响应码,如果查询的时候没有查询到数据,就给一个 404 响应码。

可以看到,删除成功后,响应码为 200:

删除失败后,响应码为 404:

3.4 修改

再来看看修改,和前面的删除类似,先查询,再修改:

@PutMapping("/")
public Mono<ResponseEntity<User>> updateUser(@RequestBody User user) {
    return userDao.findById(user.getId())
            .flatMap(u -> userDao.save(user))
            .map(u->new ResponseEntity<User>(u,HttpStatus.OK))
            .defaultIfEmpty(new ResponseEntity(HttpStatus.NOT_FOUND));
}

如果修改的数据不存在的话,就会给出一个 404 响应:

3.5 自定义查询方法

松哥之前的 Spring Data Jpa 中讲的一些查询 API,这里同样是适用的(公号后台回复 666 获取之前的教程)。

例如我们可以在 UserDao 中自定义一个查询方法:

@EnableMongoRepositories
public interface UserDao extends ReactiveMongoRepository<User,String{
    Flux<User> findUserByUsernameContaining(String name);
}

然后添加一个接口调用该方法:

@GetMapping("/byname")
public Flux<User> getUserByName(String name) {
    return userDao.findUserByUsernameContaining(name);
}

这样该接口就可以查询名字中包含某关键字的所有用户了。

其他关于 JPA 的用法这里都是适用的,因为在之前的文章中讲过,松哥这里就不再赘述了。

4.小结

好啦,今天我们就用 WebFlux 写了一个简单的 CURD,大家先来感受下 WebFlux 的基本用法,后面的文章松哥将和大家分享 WebFlux 如何连接关系型数据库,敬请期待。

TienChin 视频杀青啦~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦

Spring 源码分析视频教程连载中,感兴趣的小伙伴戳这里:Spring源码应该怎么学?

相关推荐

  • 如果你正在纠结毕设,不妨看看这个!
  • 一个支持多存储的文件列表程序,开箱即用!
  • 今年面试难度越来越大了...
  • [开源]MIT开源协议,前后端分离、美观大方后台通配权限管理系统
  • 浅谈权限系统在本地生活服务平台的应用
  • 【淘宝】什么情况下会发送 OPTIONS 请求
  • 1030.AI日报:百川大模型称一口气可处理35万个汉字
  • 日更1000天,靠知识付费赚了100W+;那些年我被割过的韭菜|生财周报
  • 解锁自动驾驶乐趣时代,DeepRacer 让机器学习“0”门槛
  • 英伟达被曝开发 ARM 架构 PC 芯片,手握 x86 的英特尔坚称:ARM 对 PC 影响“微不足道”!
  • 欠一屁股技术债仍保住工作其实也并非完全不可能
  • 一个程序员10年实现年薪百万的励志故事
  • 慢SQL的致胜法宝
  • 全新的分布式锁,功能简单且强大
  • Windows 11已原生支持11种文件存档格式,包括7-Zip和RAR
  • 关于开源创业的15件小事
  • jQuery 4.0,开发进度已完成99%
  • 十月实践总结:粗看LLM+KG知识图谱研发和落地中的虚与实
  • ChatGPT测试上传文件功能;百川推出192K长文本大模型;通义千问App安卓版上线丨AIGC大事日报
  • 昆仑万维开源130亿参数大模型!0门槛商用、多榜超Llama 2,预训练数据也开源