无法使用WebClient调用响应在地图中设置值

时间:2018-07-22 02:39:47

标签: reactive-programming spring-webflux

在进行Web客户端调用并使用上一个Mono的响应后,我无法在地图中填充值。这是我尝试的代码.parameters.size()的值变为零。能够得到为什么不填充值的原因我基本上想返回年龄(不是Mono对象)  使用block会给出一个错误block()/ blockFirst()/ blockLast()正在阻塞,这在线程反应器-http-nio-3中不支持。

Map<String, String> parameters = new HashMap<String,String>();
 Mono<Person> obj = webClient
    .post()
    .uri("dummy url")
    .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
    .retrieve()
    .bodyToMono(Person.class)
 .flatMap(resp -> {
 parameters.put("name", resp.getName());
 parameters.put("age", resp.getAge());
 return Mono.just(new Person(resp.getName(),resp.getAge()));        
 }

     );

System.out.println(parameters.size());

请提出我错了的地方以及解决方法。

1 个答案:

答案 0 :(得分:1)

由于这是关于收集和使用从先前的HTTP调用收集的某种令牌的,所以最好的选择是将所有令牌委托给ExchangeFilterFunction

ExchangeFilterFunction是在客户端为每个传出请求执行的筛选器。这是这种过滤器的非常非常幼稚的实现:

class TokenFilterFunction implements ExchangeFilterFunction {

    private final AtomicReference<String> token = new AtomicReference<>();

    @Override
    public Mono<ClientResponse> filter(ClientRequest req, ExchangeFunction next) {
        if (this.token.get() == null) {
            return fetchToken(next).then(sendRequest(req, next));
        }
        else {
            return sendRequest(req, next);
        }
    }

    private Mono<ClientResponse> sendRequest(ClientRequest req, ExchangeFunction next) {
        ClientRequest request = ClientRequest.from(req)
                .header("Token", this.token.get()).build();
        return next.exchange(request);
    }

    private Mono<Void> fetchToken(ExchangeFunction next) {
        ClientRequest tokenRequest = ClientRequest.create(HttpMethod.GET,
                URI.create("https://example.com/token")).build();
        return next.exchange(tokenRequest).doOnNext(res -> {
            this.token.set(res.headers().header("Token").get(0));
        }).then();
    }
}

这可以自动调用令牌端点,以在需要时获取令牌,并直接与您首先提出的请求进行链接。再次,这样的实现应该比处理域,错误等复杂得多。

如果您正在使用某种身份验证技术,那么可能已经在Spring Security中以一种更好的方式实现了这种过滤器。

您可以在构建阶段在客户端上对其进行配置,例如:

WebClient webClient = WebClient.builder().filter(new TokenFilterFunction()).build();