响应式编程
响应式编程(reactive programming)是一种异步编程风格,关注数据流、变化传播。
在命令式编程中,a=b+c赋值,此后b、c的值的改变不会影响到a;在响应式编程中,可以将数据变化推送给改数据的订阅者,a的值可以随着b、c值的变化自动更新,类似于angular、vue之类的MVVM框架。
Reactive 能够构建异步非阻塞的应用程序,低延迟、高吞吐量。
Spring WebFlux简介
spring web应用可以基于spring mvc,也可以基于spring webflux。
springmvc
- 基于servlet,运行在servlet容器中,常见的比如tomcat、jetty、jboss
- 阻塞式IO,一个线程处理一个请求,效率低。虽然servlet 从3.1开始支持异步非阻塞,但牺牲了其它点,一般还是用的阻塞式io。
webflux
- spring5新增的组件,响应式编程(Reactive Programming),基于reactive实现
- 异步非阻塞,一个线程可以同时处理多个请求,用少量的线程就可以处理大量的请求
- 运行在支持异步非阻塞的容器中,常见的比如netty。servlet从3.1开始也支持异步非阻塞,webflux也可以运行在高版本的tomcat、jetty等支持servlet 3.1的容器中。
webflux的特点 | 优缺点
- 异步非阻塞,速度不一定比springmvc快,但支持的并发量往往比springmvc高得多,极大地提高了系统的吞吐量,适合在机器性能不足的情况下用来提高系统吞吐量
- 支持函数式编程,调试难度比spring webmvc大
各自的技术栈
WebFlux使用示例
pom.xml
创建时勾选Spring Reactive Web,也可以手动添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
- sring mvc勾选的是 Web -> Spring Web,对应 spring-boot-starter-web,默认以tomcat作为内置的servlet容器,已经包含了tomcat的依赖
- spring webflux勾选的是Web -> Spring Reactive Web,对应 spring-boot-starter-webflux,默认以netty作为web容器,已经包含了netty的依赖
可以更换内置的web容器,排除内置容器的依赖,引入其它容器的依赖即可,
controller
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
/**
* 返回基础类型
*/
@PostMapping("add")
public Mono<String> addUser(User user) {
if (Boolean.TRUE.equals(userService.addUser(user))) {
return Mono.just("操作成功");
}
return Mono.just("操作失败");
}
/**
* 返回user对象
*/
@GetMapping("id/{id}")
public Mono<User> findUserById(@PathVariable("id") Integer id) {
//Mono.just()参数不能是null,justOrEmpty()参数可以是null
Mono<User> userMono = Mono.justOrEmpty(userService.findUserById(id));
return userMono;
}
/**
* 返回user对象列表
*/
@GetMapping("username/{username}")
public Flux<User> findUserByUsername(@PathVariable("username") String username) {
List<User> userList = userService.findUserByUsername(username);
if (userList != null) {
//Flux.from系列方法,参数不能为null
return Flux.fromIterable(userList);
}
return Flux.empty();
}
}
相比于直接返回对象,返回包装对象的Flux、Mono是非阻塞写法。
Mono用于返回单个对象(0或1个元素),Flux用于返回多个对象(以列表形式返回,列表中可以包含0个或多个对象)。