随着响应式编程在网络编程中使用越发的普及,mysql等一系列的关系型数据库也在r2dbc等包的帮助下支持响应式。虽然响应式跟原来的sevlet的写法区别比较大,但是spring尽量保持原来的风格,编写control层和service层的方法跟原来基本相同,略有区别就是controller返回的Mono或是Flux。特别是对crud的支持,跟原来的jpa基本相同。
例子:
1、创建table
在mysql数据库中创建一个命名为mydb的数据库,然后创建一个命名为employee的表用于测试, 字段内容如下:
id
name: 员工姓名
age:员工年龄
salary:员工薪酬
CREATE DATABASE IF NOT EXISTS mydb;
USE mydb;
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`age` int(11) NOT NULL,
`salary` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
BEGIN;
INSERT INTO `employee` VALUES ('1', 'ffzs', '20', '110000'), ('2', 'dz', '30', '2000000');
COMMIT;
2、创建spring项目
使用gradle维护项目,使用的支持:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'dev.miku:r2dbc-mysql'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'io.projectreactor:reactor-test'
}
3、编写配置文件
主要配置mysql的链接,r2dbc链接的url跟jdbc的略有不同,需要注意
application.yml
spring:
r2dbc:
url: r2dbcs:mysql://localhost:3306/mydb?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
username: root
password: 123zxc
4、编写model类
Employee.class
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@With
@Table("employee")
public class Employee {
@Id
private long id;
private String name;
private long age;
private long salary;
}
5、 dao层编写
跟jpa使用基本相同,不过这里继承的事响应式的crud类ReactiveCrudRepository
public interface EmployeeDao extends ReactiveCrudRepository {
Flux findByName(String name);
}
6、service层编写
编写了常见的增删改查的功能
跟之前的不同之处是这里返回的值为Reactor的对象Flux或Mono
@Service
@RequiredArgsConstructor
public class EmployeeService {
private final EmployeeDao employeeDao;
public Flux findAll () {
return employeeDao.findAll();
}
public Mono findById (long id) {
return employeeDao.findById(id);
}
public Flux findByName (String name) {
return employeeDao.findByName(name);
}
public Mono save (Employee employee) {
return employeeDao.save(employee);
}
public Mono update (Employee employee) {
return findById(employee.getId())
.map(em -> employee.withId(em.getId()))
.flatMap(employeeDao::save)
.then();
}
public Mono delete (Employee employee) {
return employeeDao.delete(employee);
}
public Mono deleteById (long id) {
return employeeDao.deleteById(id);
}
}
7、controller层编写
应用RESTful api 特点,一个路由可以有get,post,put,delete四种功能
跟service层对应实现增删改查的功能
@RestController
@RequiredArgsConstructor
@RequestMapping("employee")
@Slf4j
public class EmployeeController {
private final EmployeeService employeeService;
@GetMapping
public Flux findAll() {
return employeeService.findAll();
}
@GetMapping (path = "{id}")
public Mono findById(@PathVariable("id") long id) {
return employeeService.findById(id);
}
@GetMapping ("find")
public Flux findByName(@RequestParam("name") String name) {
return employeeService.findByName(name);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono save(@RequestBody Employee employee) {
return employeeService.save(employee);
}
@PutMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public Mono update (@RequestBody Employee employee) {
return employeeService.update(employee);
}
@DeleteMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public Mono delete (@RequestBody Employee employee) {
return employeeService.delete(employee);
}
@DeleteMapping(path = "{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public Mono deleteById (@PathVariable long id) {
return employeeService.deleteById(id);
}
}
8、测试
项目集成springdoc的openapi(可以理解为swagger)进行api接口测试,添加依赖:
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.4.1'
不用做任何修改直接运行项目即可, 成功启动:
访问swagger测试页面 http://localhost:8080/swagger-ui.html,就会完成跳转到测试页面:
代码