webflux 之 常用变量说明

简介

Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架。 
与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞, 并通过Reactor项目实现Reactive Streams规范。
并且可以在诸如Netty,Undertow和Servlet 3.1+容器的服务器上运行。

Reactor中的Mono和Flux

Flux 和 Mono 是 Reactor 中的两个基本概念。Flux 表示的是包含 0 到 N 个元素的异步序列。 在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。 当消息通知产生时,订阅者中对应的方法 onNext(), onComplete()和 onError()会被调用。Mono 表示的是包含 0 或者 1 个元素的异步序列。 该序列中同样可以包含与 Flux 相同的三种类型的消息通知。Flux 和 Mono 之间可以进行转换。 对一个 Flux 序列进行计数操作,得到的结果是一个 Mono对象。把两个 Mono 序列合并在一起,得到的是一个 Flux 对象。

了解更多 别人写的。

官网

我的理解:

Mono:0-1个元素
Flux:0-N个元素

二者都是发布者(publisher)

流之间的传递都是这两个数据结构。

介绍两个函数:

flatMap:要操作数据,并返回一个Mono。当没有返回时使用then创建一个Mono数据返回
map:不操作数据,只是转化

WebFlux的使用方式

 如图所示,WebFlux支持两种编程方式

  • 基于SpringMvc注解@Controller
  • 基于Java8 lambda样式路由和处理

springboot引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--reactor的测试依赖-->
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

示例

基于SpringMvc注解

与使用SpringMvc不同的是使用Spring WebFlux使用Mono<>,Flux<>对象统一返回数据,如下

Controller代码: 

@RestController
@RequestMapping("/api/user")
public class WebFluxController {

    private Map<Long,User> map = new HashMap<Long,User>(10);
    @PostConstruct
    public void init(){
        map.put(1L,new User(1,"admin","admin"));
        map.put(2L,new User(1,"admin2","admin2"));
        map.put(3L,new User(1,"admin3","admin3"));
    }
    @GetMapping("/getAll")
    public Flux<User> getAllUser(){
        return Flux.fromIterable(map.entrySet().stream().map(Map.Entry::getValue)
                .collect(Collectors.toList()));
    }
    @GetMapping("/{id}")
    public Mono<User> getUserById(@PathVariable("id") Long id){
        return Mono.just(map.get(id));
    }
    @PostMapping("/save")
    public Mono<ResponseEntity<String>> save(@RequestBody User user){
        map.put(user.getUid(),user);
        return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED));
    }
}

业务功能代码:

处理请求的类,实现具体的业务逻辑,接口 ServerRequest 表示的是一个 HTTP 请求体。通过ServerRequest 对象可获取到请求的相关信息,如请求路径、查询参数和请求内容等。方法 的返回值是一个 Mono对象。接口 ServerResponse 用来表示 HTTP 响应。ServerResponse 中包含了很多静态方法来创建不同 HTTP 状态码的响应对象

@Component
public class UserHandler {

    private IUserService userService;
    @Autowired
    public UserHandler(IUserService userService) {
        this.userService = userService;
    }

    public Mono<ServerResponse> getAllUser(ServerRequest serverRequest){
        Flux<User> allUser = userService.getAllUser();
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class);
    }

    public Mono<ServerResponse> getUserById(ServerRequest serverRequest){
        //获取url上的id
        Long uid = Long.valueOf(serverRequest.pathVariable("id"));
        Mono<User> user = userService.getUserById(uid);
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(user,User.class);
    }

    public Mono<ServerResponse> saveUser(ServerRequest serverRequest){
        Mono<User> user = serverRequest.bodyToMono(User.class);
        return ServerResponse.ok().build(userService.saveUser(user));
    }

}

设置路由

@Configuration
public class RoutingConfiguration {

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler){
        return route(GET("/api/user").and(accept(MediaType.APPLICATION_JSON)),userHandler::getAllUser)
                .andRoute(GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)),userHandler::getUserById)
                .andRoute(POST("/api/save").and(accept(MediaType.APPLICATION_JSON)),userHandler::saveUser);
    }

}

完整代码

这里补充一个概念:

异步用到SSE技术。

SSE:Server send Event:服务端发送事件(HTML5支持该技术)

当客户端向服务端发送请求,服务端会抓住这个请求不放,等有数据更新的时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求,周而复始。这种方式的好处是减少了服务器的请求数量,大大减少了服务器的压力

RouterFunction模式一般开发过程

1.HandlerFunction(输入ServerRequest返回ServerResponse)
2.RouterFunction(请求URL和HandlerFunction对应起来)
3.将RouterFunction包装为HttpHandler
4.交给Server处理,主要是netty或者servlet

一般业务开发者用到的不全,得到Mono或者Flux处理业务流程即可。

当然你可以自己写一个框架。

这里有一个示例,可以下载去看一下。

链接

说明:

本文大部分内容来自:https://blog.csdn.net/qq_15144655/article/details/80708915

其中加了一下自己的理解。

再次对原作者表示感谢。

发布了155 篇原创文章 · 获赞 11 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013919153/article/details/105053802