webflux客户端发请求处理响应时遇到的

研究exchangeFunction和WebClient的用法时,无意踩到个坑,下面代码的exchangeFunctionWithResponse2,执行时异常:

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-4
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:77)
at reactor.core.publisher.Mono.block(Mono.java:1494)

搜索后得出初步结论:

  1. netty的线程不允许阻塞,因为是在netty的pipeline里,而netty的线程本身是不允许阻塞的。我自己虽然用过netty多次,确实没有遇到过需要阻塞它的onRead线程,虽然没试过是不是真的netty线程不允许阻塞,但想必是没有这样用的情景。
  2. 不要在map或者flatMap的mapper或者transformer中使用block。这样会违背响应式的初衷,如果要使用block,使用restTemplate
    public static void exchangeFunction() {
        ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector());
        ClientRequest request = ClientRequest
            .create(HttpMethod.GET, URI.create("http://demo.com/basic-auth/user/passwd"))
            .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .build();
        exchangeFunctionWithString(request, exchangeFunction);
        exchangeFunctionWithResponse(request, exchangeFunction);
        exchangeFunctionWithResponse2(request, exchangeFunction);
    }

    private static void exchangeFunctionWithResponse(ClientRequest request, ExchangeFunction exchangeFunction) {
        Mono<ClientResponse> exchange = exchangeFunction.exchange(request);
        ClientResponse clientResponse = exchange.block();
        String body = clientResponse.body(new MyBodyExtractor());
        log.info("status code: {}, body: {}", clientResponse.statusCode(), body);
    }

    private static void exchangeFunctionWithResponse2(ClientRequest request, ExchangeFunction exchangeFunction) {
        Mono<ClientResponse> exchange = exchangeFunction.exchange(request);
        Mono<String> bodyMono = exchange
            .map(clientResponse -> clientResponse.body(new MyBodyExtractor())); // block在map的mapper中会引起exception
        log.info("body: {}", bodyMono.block());
    }

    static class MyBodyExtractor implements BodyExtractor<String, ReactiveHttpInputMessage> {
        public String extract(ReactiveHttpInputMessage inputMessage, Context context) {
            ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() {};
            BodyExtractor<Mono<String>, ReactiveHttpInputMessage> delegate = BodyExtractors.toMono(type);
            return delegate
                .extract(inputMessage, context)
                .block();
        }
    }

    // prints response message in string.
    private static void exchangeFunctionWithString(ClientRequest request, ExchangeFunction exchangeFunction) {
        Mono<String> result = exchangeFunction
            .exchange(request)
            .flatMap(clientResponse -> clientResponse.bodyToMono(String.class));
        String block = result.block();
        log.info("receive body: {}", block);
    }

    public static void main(String[] args) {
        exchangeFunction();
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值