【问题标题】:Spring Webclient is not calling another serviceSpring Webclient 没有调用另一个服务
【发布时间】:2022-01-08 18:14:56
【问题描述】:

我正在尝试从我的 Spring Cloud Gateway 服务调用另一个服务。

AuthenticationServiceClientWebclient 应该调用所需的服务,但它没有。

我找不到我做错了什么。

这是AuthenticationServiceClient.class的实现:

public class AuthenticationServiceClientImpl implements AuthenticationServiceClient {

private final WebClient webClient;

@Autowired
public AuthenticationServiceClientImpl(WebClient.Builder builder) {

    this.webClient = builder.baseUrl("http://localhost:9002").build();
}

@Override
public Mono<AppUser> getAppUser(String accessToken) {

    return this.webClient.get().uri
                    (uriBuilder ->
                            uriBuilder
                                    .path("/api/authentication-service/get-user-detail")
                                    .queryParam("accessToken", accessToken)
                                    .build()
                    )
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .onStatus(HttpStatus::isError, error -> Mono.just(new RuntimeException("Error from AUTHENTICATION SERVICE")))
            .bodyToMono(AppUser.class);
}

}

这是AuthenticationFilter.class

public class AuthenticationFilter implements GatewayFilter {

private final AuthenticationServiceClient authClient;

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    ServerHttpRequest request = exchange.getRequest();

    final String token = this.getAuthHeader(request);

    authClient.getAppUser(token).flatMap(response -> {
        System.out.println(response);
        this.populateRequestWithHeaders(exchange, response);
        return chain.filter(exchange);
    });

    return this.onError(exchange, "Authorization header is invalid", HttpStatus.UNAUTHORIZED);
}
}

为简洁起见,省略了一些代码和注释。

【问题讨论】:

  • 不确定您是如何实现 populateRequestWithHeaders() 方法的,但要修改您需要变异的请求。在此处查看示例 - programcreek.com/java-api-examples/…
  • "在您订阅之前什么都不会发生。" - 你有一个悬挂的 Mono,你使用 authClient

标签: java spring-webflux spring-cloud-gateway spring-webclient


【解决方案1】:

你的问题在这里:

// You are ignoring the return and breaking the chain
authClient.getAppUser(token).flatMap(response -> {
        System.out.println(response);
        this.populateRequestWithHeaders(exchange, response);
        return chain.filter(exchange);
    });

您需要处理返回的Mono,以便框架可以subscribe 对其进行处理。

return authClient.getAppUser( ... )

这一行:

return this.onError(exchange, "Authorization header is invalid", HttpStatus.UNAUTHORIZED);

应该完全删除。如果你想处理错误,你应该使用error operator

return authClient.getAppUser( ... ).onErrorResume( ... ) // one of many error operators

问题是你在编程时是在命令式地思考。您正在继续flatMap 中的过滤器链,但由于您破坏了返回链,因此不会调用任何一个。

spring reactor 将在有人调用您的服务时,首先调用上游的操作符以构建操作符链(这称为组装阶段),直到找到producer 的数据。然后它会开始调用下游的操作符,开始为调用客户端生成数据。

但是你打破了这个链条,这就是为什么你的休息电话没有被调用。

我建议你阅读 reactor 官方文档的getting started section,因为这是使用响应式编程时的基本知识。

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2019-10-24
    • 2017-04-01
    相关资源
    最近更新 更多