1、介绍
R2DBC(Reactive Relational Database Connectivity)是在2018年Spring One Platform大会被提出来的,它旨在使用完全无阻塞驱动程序创建数据库链接,为SQL数据库创建响应式API。为了探索R2DBC我们将创建一个简单的WebFlux应用实现目标
2、项目配置
我们通过Spring Initializr创建一个新的项目,如下图所示选择我们需要的依赖。确保Spring Boot的版本大于等于2.3.0。因为在此版本之后才开始支持MYSQL的响应式驱动
Maven依赖如下:``
<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>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<scope>runtime</scope>
</dependency>
3、脚本准备
create table test.users
(
id bigint auto_increment,
first_name varchar(50) null,
last_name varchar(50) null,
created_at datetime null,
updated_at datetime null,
constraint users_id_uindex
unique (id)
);
alter table test.users
add primary key (id);
4、应用代码
4.1 实体对象
注意这里用的日期类型是java.time.LocalDateTime,默认不能使用java.sql.Date、java.util.Date、java.sql.Timestamp类型,否则会提示错误。默认支持的类型转换参考org.springframework.data.r2dbc.convert.R2dbcConverters类。
@Table(value = "users")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class User {
@Id
private Long id;
@Column(value = "first_name")
private String firstName;
@Column(value = "last_name")
private String lastName;
@Column(value = "created_at")
private LocalDateTime createdAt;
@Column(value = "updated_at")
private LocalDateTime updatedAt;
}
4.2 控制层代码
/**
* 支持增加、修改、删除、查询
* @date 2020-05-24
* @author 稻草鸟人
*/
@RestController
@RequestMapping("/v1")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping(path = "/users/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(code = HttpStatus.OK)
public Mono<User> getUser(@PathVariable("id") Long id) {
Mono<User> userMono = userService.find(id);
return userMono;
}
@PutMapping("/users/{id}")
public Mono<User> update(@PathVariable("id") Long id, @RequestBody User user) {
return this.userService.find(id)
.map(u -> {
u.setFirstName(user.getFirstName());
u.setLastName(user.getLastName());
return u;
})
.flatMap(u -> save(u));
}
@DeleteMapping("/users/{id}")
public Mono<Void> delete(@PathVariable("id") Long id) {
return userService.delete(id);
}
@PostMapping("/users")
public Mono<User> save(@RequestBody User user) {
return userService.save(user);
}
其他代码不再贴了,具体参考下面的源码部分
5、简单测试
目前只是简单的测试,后面我们做一次简单的压测,比较下非阻塞接口和同步接口的性能差异吧!