spring boot webflux响应式二探

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战。 上次学习了springboot webFlux的简单开发工作,今天继续学习webFlux。在实际的开发工作中,我们有时需要返回单个数据,有时需要返回集合数据和MAP数据。而在webFlux中所有的返回都是通过Flux或Mono包装返回。 一、数据响应 1、返回单个对象 /mono

@GetMapping("mono")
public Mono<Object> mono() {
    return Mono.create(monoSink -> {
        log.info("创建 Mono");
        monoSink.success("hello webflux");
    })
            .doOnSubscribe(subscription -> { //当订阅者去订阅发布者的时候,该方法会调用
                log.info("subscription={}", subscription);
            }).doOnNext(o -> { //当订阅者收到数据时,改方法会调用
                log.info("o={}", o);
            });
}
复制代码

2、返回List数据 /userList

//返回List集合
@GetMapping("userList")
public Flux<User> userList() {
    List<User> list = new ArrayList<>();
    IntStream.range(1,10).forEach(i->{
        User user = new User("No:1000"+i,"jack",
                "1899976965",
                "[email protected]","南路木",new Date());
        list.add(user);
    });
    return Flux.fromIterable(list);
}
复制代码

3、返回Map数据 /userMap

@GetMapping("userMap")
public Flux<Map.Entry<String, User>> userMap() {
    Map<String, User> map = new HashMap<>();
    IntStream.range(1,10).forEach(i->{
        User user = new User("No:1000"+i,"jack",
                "1899976965",
                "[email protected]","南路木",new Date());
        map.put(user.getId(),user);
    });

    return Flux.fromIterable(map.entrySet());
}
复制代码

集合数据通过Flux.fromIterable的方法处理。

二、WebClient的使用 开发响应式HTTP请求就需要用到webClient。 1、创建WebClient对象并指定baseUrl; 2、指定HTTP请求方式GET/POST; 3、异步地获取response信息; 4、将response body解析为字符串。

@RequestMapping("test1")
public void clientTest(){
    WebClient webClient = WebClient.create("http://localhost:8080");   // 1
    Mono<String> resp = webClient
            .get().uri("/flux/hello") // 2
            .retrieve() // 3
            .bodyToMono(String.class);  // 4
        resp.subscribe(System.out::println);    // 5
    try {
        TimeUnit.SECONDS.sleep(1);  // 6
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
复制代码

这样/test1方法就能访问http://localhost:8080/flux/hello的接口数据。

@RequestMapping("test2")
public Flux<User> clientTest2() throws InterruptedException {
    WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build(); // 1
    return webClient
            .get().uri("/flux/user")
            .accept(MediaType.APPLICATION_STREAM_JSON) // 2
            .exchange() // 3
            .flatMapMany(response -> response.bodyToFlux(User.class))   // 4
            .doOnNext(System.out::println)  // 5
            .blockLast();   // 6
            ;
}
复制代码

1、这次使用WebClientBuilder来构建WebClient对象; 2、配置请求Header:Content-Type: application/stream+json; 3、获取response信息,返回值为ClientResponse,retrive()可以看做是exchange()方法的"快捷版"; 4、使用flatMap来将ClientResponse映射为Flux; 5、只读地peek每个元素,然后打印出来,它并不是subscribe,所以不会触发流; 6、blockLast方法,顾名思义,在收到最后一个元素前会阻塞,响应式业务场景中慎用。

三、浏览器定时响应的例子

//每秒会给浏览器推送数据
@GetMapping(value = "/interval", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
private Flux<String> flux() {
    Flux<String> result = Flux
            .fromStream(IntStream.range(1, 13).mapToObj(i -> {
               log.info("i="+i);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                return "this data is " + i;
            }));
    return result;
复制代码

下一节继续学习WebFlux的WebSocket的异步处理及连接spring Data的使用。

Guess you like

Origin juejin.im/post/7031181439374721060