Spring Reactive WebFlux初识
- 开篇
- Sring Reactive
- 1、flux
- 2、Mono
- 创建第一个WebFlux程序
- 对数据库实现CRUD
- 结束
开篇
最近进入公司开始实习了,根据要求自己学习Spring Reactive,然后编写一个小demo,在这里就分享自己的学习过程
Sring Reactive
Reactive是函数式编程(Functional),管道流(pipeline, stream), 异步非阻塞的,事件驱动的。我们主要学习的是Spring5 中新增的ReactiveWeb,也就是WebFlux框架,一个响应式的框架技术。
响应式编程,为什么要使用响应式编程,传统的编程是顺序执行的,一个程序需要一直等待,直到上一个程序结束才能执行,采用响应式编程,就无需等待,适合高并发。
Reactive很大一部分可以参考Reactor来学习,WebFlux中以流的形式传输数据,它所支持的格式有两种,Mono和Flux。
1、flux
flux表示的是包含0到n个元素的异步序列,该序列中可以包含三种不同类型的消息:
①正常的包含元素的消息
②序列结束的消息
③序列出错的消息
2、Mono
Mono表示的是包含0或者1个元素的异步序列,也同样可以包含与flux相同的三中类型的消息。
Flux与Mono之间可以相互转换。比如对一个Flux序列进行计数操作就可以得到一个Mono对象
将两个Mono序列合并在一起得到一个Flux对象
创建第一个WebFlux程序
我们准备使用IDEA进行编码,数据库使用MySQL(连接包使用R2DBC):
- 打开IDEA,顺序点击File->new->project,选择Spring Initializr ,这里建议大家不要使用Default,转而使用国内阿里云的库去下载,会很快(赞),然后Next;
- 创建自己的包名,项目名,选择jdk 的版本,next;
- 根据图中的提示,选择相应的依赖包,next,然后更改一下存储位置就可以点击finish;
- 创建好的项目就会如图所示;
- 然后,我们来添加一个连接池,再配置数据库的连接;
- 连接池以及连接数据库,都要自己添加一个依赖:
<!-- r2dbc 连接池 -->
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-pool</artifactId>
</dependency>
<!--r2dbc mysql 库-->
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
</dependency>
- 接下来我们写一个简单的controller测试一下;
- 运行程序,查看运行结果;
- 我们可以看到,程序已经成功运行起来了。
对数据库实现CRUD
- 创建如下目录结构
- 编写实体类代码
package com.example.demo.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.io.Serializable;
@Table("student")
public class Student implements Serializable {
@Id
private Integer sid;
private String sname;
private String gender;
private Integer age;
private String school;
public Student() {
}
public Student(Integer sid, String sname, String gender, Integer age, String school) {
this.sid = sid;
this.sname = sname;
this.gender = gender;
this.age = age;
this.school = school;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", school='" + school + '\'' +
'}';
}
}
- 编写数据处理代码
package com.example.demo.dao;
import com.example.demo.entity.Student;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
public interface StudentRepository extends ReactiveCrudRepository<Student,Integer> {
/*
* 这里使用了Reactive的数据处理接口ReactiveCrudRepository
*
* 可以编写自定义的数据处理接口
*
* 方法类似于JPA,例如:
* findBySid、findBySname
*
* 也就是:find+By+对应的字段名,注意使用驼峰命名法
* */
}
- 编写业务逻辑层
package com.example.demo.service;
import com.example.demo.entity.Student;
import reactor.core.publisher.Mono;
public interface StudentService {
Mono searchById(Integer sid);
Mono add(Student student);
Mono modify(Student student);
Mono del(Integer sid);
}
- 编写业务实现层
package com.example.demo.service.impl;
import com.example.demo.dao.StudentRepository;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;
@Service
@Transactional
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentRepository studentRepository;
@Override
public Mono searchById(Integer sid) {
return studentRepository.findById(sid);
}
@Override
public Mono add(Student student) {
return studentRepository.save(student);
}
@Override
public Mono modify(Student student) {
return studentRepository.save(student);
}
@Override
public Mono del(Integer sid) {
return studentRepository.deleteById(sid);
}
}
- 编写控制层访问接口
package com.example.demo.controller;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/stu")
public class StudentController {
@Autowired
private StudentService studentService;
//查询接口
@GetMapping("/{id}")
public Mono findById(@PathVariable("id")Integer id){
return studentService.searchById(id);
}
//增加接口
@PostMapping("/")
public Mono add(@RequestBody Student student){
return studentService.add(student);
}
//修改接口
@PutMapping("/")
public Mono modify(@RequestBody Student student){
return studentService.modify(student);
}
//删除接口
@DeleteMapping("/{id}")
public Mono delete(@PathVariable("id") Integer id){
return studentService.del(id);
}
}
- 最后,就可以进行测试了
我使用的PostMan进行的接口测试,正常运行!