松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里-->Spring Boot+Vue+微人事视频教程
不知不觉中,我们的 WebFlux 系列已经整到第 11 篇啦。如果小伙伴们还没看过前面的文章,记得先看一下哦,这有助于理解本文。
好啦,开始今天的正文。
前面我们用 WebFlux 已经写了一个 CURD 了,不过数据库用的是 MongoDB。很多人对 WebFlux 持怀疑态度,包括松哥之前发文章的时候,还有人在说不能连接 MySQL 的 WebFlux 是没有任何意义的!这句话没错,但是我们也要看到 WebFlux 正处于一个高速发展的时期,所有不可能的事情都会变得可能,所有以前没有的功能以后都会有,WebFlux 的变化速度是肉眼可见的。
比如我们今天要介绍的 R2DBC 就能在一定程度上打消一些人的疑虑,虽然这个工具还不是特别完美,但是我们看到了 WebFlux 在努力解决这些存在的问题,我们也有理由相信 WebFlux 未来会越来越好。
好啦,不吹了,还是来看点实际的东西吧。
首先大家要知道,我们最常使用的 JDBC 其实是同步的,而我们使用 WebFlux 的目的是为了通过异步的方式来提高服务端的响应效率,WebFlux 虽然实现了异步,但是由于 JDBC 还是同步的,而大部分应用都是离不开数据库的,所以其实效率本质上还是没有提升。
那么怎么办呢?有没有异步的 JDBC 呢?有!
目前市面上异步 JDBC 主要是两种:
需要注意的是,这两个都不是对原来 JDBC 的补充,都是打算重新去设计数据库访问方案!
好了,现在大家对 R2DBC 有一个基本的认知了,接下来我们就通过一个简单的例子,我们一起来体验一把如何通过 R2DBC 来操作 MySQL 数据库。
首先我们来创建一个 Spring Boot 项目,引入 WebFlux 和 R2DBC 依赖,如下图:
项目创建成功后,pom.xml 文件中会自动加入 R2DBC 相关的依赖,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
接下来我们在 application.properties 中配置数据库的连接信息,注意这次的配置和之前的有些不同:
spring.r2dbc.url=r2dbcs:mysql://localhost:3306/test01
spring.r2dbc.username=root
spring.r2dbc.password=123
配置文件除了属性的 key 不同之外,数据库的连接协议也从 jdbc 变为 r2dbc 了。
OK,如此,我们的准备工作就算完成了。
我们准备一个简单的数据表,如下:
这个脚本很简单,应该不用我提供了吧。
我们首先来提供一个实体类,如下:
public class User {
@Id
private Long id;
private String username;
private String address;
//省略 getter/setter
}
然后我们需要一个 UserRepository 接口,这个接口直接继承自 ReactiveCrudRepository 即可,这跟之前 MongoDB 的玩法比较类似。
public interface UserRepository extends ReactiveCrudRepository<User,Long> {
}
接下来我们来定义 User 表的处理器,这个也跟之前 MongoDB 中的差不多,如下:
import static java.lang.Long.parseLong;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.ServerResponse.notFound;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
@Component
public class UserHandler {
@Autowired
UserRepository userRepository;
public Mono<ServerResponse> getAllUsers(ServerRequest serverRequest) {
return ok().contentType(APPLICATION_JSON)
.body(userRepository.findAll(), User.class);
}
public Mono<ServerResponse> addUser(ServerRequest serverRequest) {
return ok().contentType(APPLICATION_JSON)
.body(userRepository.saveAll(serverRequest.bodyToMono(User.class)), User.class);
}
public Mono<ServerResponse> deleteUser(ServerRequest serverRequest) {
return userRepository.findById(parseLong(serverRequest.pathVariable("id")))
.flatMap(user -> userRepository.delete(user).then(ok().build()))
.switchIfEmpty(notFound().build());
}
}
最后我们再来配置请求地址路由,如下:
@Configuration
public class RouterConfiguration {
@Bean
RouterFunction<ServerResponse> userRouterFunction(UserHandler userHandler) {
return RouterFunctions.nest(RequestPredicates.path("/user"),
RouterFunctions.route(RequestPredicates.GET("/"), userHandler::getAllUsers)
.andRoute(RequestPredicates.POST("/"), userHandler::addUser)
.andRoute(RequestPredicates.DELETE("/{id}"), userHandler::deleteUser));
}
}
这一块其实都没啥好说的,如果大家感到困惑,可以参考我们前两篇文章中的讲解。
最后我们来简单测试下。
查询:
添加:
更新:
有 id 并且 id 已经存在,默认就是更新。
删除:
删除成功响应 200:
删除成功响应 200
删除失败响应 404:
删除失败响应 404
好啦,这就是一个简单的 WebFlux 操作关系型数据库的案例,关于 WebFlux 的更多其他用法,跟随松哥一起来慢慢解剖吧~