SpringBoot实战派读书笔记---响应式编程

1.什么是WebFlux?
WebFlux不需要Servlet API,在完全异步且无阻塞,并通过Reactor项目实现了Reactor Streams规范 。
WebFlux可以在资源有限的情况下提高系统的吞吐量和伸缩性 。
WebFlux除支持Restful Web服务外,还可以用于提供动态HTML内容 。
2.比较MVC和WebFlux
SpringMVC采用命令式编程的方式,代码被一句一句的执行,便于开发者理解与调试代码,WebFlux则是基于异步响应式编程!
1.工作方式
MVC
MVC的工作流程是:主线程接收到请求(request)-> 准备数据 ->返回数据 。
整个过程是单线程阻塞的,用户会感觉等待时间长是因为,在结果处理好之后才会返回结果给浏览器 。。因此,如果请求过多,则吞吐量会上不去 。
WebFlux
工作流程:主线程接收到请求 -> 立刻返回数据与函数的组合 -> 开启一个新的work线程去做实际的数据准备工作,进行真正的业务操作 -> work线程完成工作 -> 返回用户真实数据(结果)
这种方式给人的感觉是响应时间很短,因为返回的是不变的常数,它不随用户数量的增加而变化!不支持MySql等关系型数据库 。
3/认识Mono和Flux
Mono和Flux属于事件发布者,为消费者提供订阅接口 。当有事件发生时,Mono和Flux会回调消费者的相应方法,然后通知消费者相应的事件 。
Mono和Flux用于处理异步数据流,它不像MVC中那样直接返回String/list,而是将异步数据流包装Mono和Flux对象 。
Mono和Flux的区别
Mono主要用于返回单个数据,Flux主要用于返回多个数据 。
举例:如果要根据id查询某个User对象,则返回的肯定是单个User,那么需要将其包装成Mono<User>
若需要获取所有User,则需要将这个集合包装成Flux<User>.这里的单个数据并不是指的是一个数据,而是指一个封装好的对象 。多个数据就是多个对象 。
开发WebFLux的流程
1.注解式开发流程
WebFLux是响应式框架 。地址映射也是通过@RequestMapping提供的,用@Controller和@RestController来代替Handler类 。
2.响应式开发流程
1.创建handler类
这里的handler类相当于SpringMVC的Controller层中的方法体 。在响应式编程中,请求和相应不再是HttpServletRequest和HttpServletResponse,而是变成了ServerRequest和ServerResponse 。
2.配置RouterFunction
RouterFunction和注解@RequestMapping类似,都用于提供URL路径 。
实例:用注解式开发实现数据的增加,删除,修改和查询
首先创建实体类
package com.example.demo.webFlux.entity;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructorpublic class User {private long id;private String name;private int age;}然后编写控制器,实现WebFlux操作数据功能,
package com.example.demo.controller;import com.example.demo.webFlux.entity.User;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;import javax.jws.soap.SOAPBinding;import java.util.HashMap;import java.util.Map;import java.util.stream.Collectors;@RestController@RequestMapping(path = "/user")public class UserController {Map<Long, User> users = new HashMap<>();@PostConstructpublic void init() throws Exception{users.put(Long.valueOf(1),new User(1,"Curry",34));users.put(Long.valueOf(2),new User(2,"Iverson",44));}/** 获取所有用户* */@GetMapping("/list")public Flux<User> getAll(){return Flux.fromIterable(users.entrySet().stream().map(entry->entry.getValue()).collect(Collectors.toList()));}/** 获取单个用户* */@GetMapping("/{id}")public Mono<User> getUser(@PathVariable Long id){return Mono.justOrEmpty(users.get(id));}/** 创建用户* */@PostMapping("")public Mono<ResponseEntity<String>> addUser(User user){users.put(user.getId(),user);return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED));}/** 修改用户* */@PutMapping("/{id}")public Mono<ResponseEntity<User>> putUser(@PathVariable Long id,User user){user.setId(id);users.put(id,user);return Mono.just(new ResponseEntity<>(user,HttpStatus.CREATED));}/** 删除用户* */@DeleteMapping("/{id}")public Mono<ResponseEntity<String>> deleteUser(@PathVariable Long id){users.remove(id);return Mono.just(new ResponseEntity<>("删除成功",HttpStatus.ACCEPTED));}}

经验总结扩展阅读