Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ExchangeFilterFunction是否在WebClient反应流外部执行代码?_Java_Spring_Spring Webflux_Spring Webclient - Fatal编程技术网

Java ExchangeFilterFunction是否在WebClient反应流外部执行代码?

Java ExchangeFilterFunction是否在WebClient反应流外部执行代码?,java,spring,spring-webflux,spring-webclient,Java,Spring,Spring Webflux,Spring Webclient,我正在为WebClient请求期间的扩展日志创建ExchangeFilterFunction 问题:在下面的示例中,如果在.doOnNext()函数中执行日志记录,会有什么区别吗?或者他们在处理上是平等的 ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { LOGGER.info("Request url=" + clientResponse.url() + ", method=" + clientRespons

我正在为
WebClient
请求期间的扩展日志创建
ExchangeFilterFunction

问题:在下面的示例中,如果在
.doOnNext()
函数中执行日志记录,会有什么区别吗?或者他们在处理上是平等的

ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
    LOGGER.info("Request url=" + clientResponse.url() + ", method=" + clientResponse.method());
    return Mono.just(clientRequest);
});

ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
    return Mono.just(clientRequest).doOnNext(clientResponse2 -> {
        LOGGER.info("Request url=" + clientResponse2.url() + ", method=" + clientResponse2.method());
    });
});

一个比另一个有什么优势吗?

我只是不愿意在你的流程中人为地引入
Mono。只是
或类似的东西。我认为
.doOnNext
是一个额外的步骤,但我无法想象它会有什么不同。最好避免中断流程。我认为那将是你表现最差的点球

注意:如下所述,当调用
WebClient
时,这会记录下来,通常看起来比使用方便的方法更难看,但它避免使用
Mono.just

@Override
public void run(ApplicationArguments args) throws Exception {
    WebClient webClient = WebClient.builder()
            .baseUrl("http://localhost:8080/")
            .filter(eff)
            .build();
    webClient.get().retrieve().bodyToMono(String.class).subscribe(System.out::println);
}

ExchangeFilterFunction eff = (cr,ef)->{
    System.out.println("method: " + cr.method());
    return ef.exchange(cr)
    .map(cresp->{
        System.out.println(cresp.rawStatusCode());
        return cresp;
    });
};

在这种特殊情况下,webclient将正确调用过滤器。但是,总体上要注意这一点

在第一种情况下,当调用方法时将发生日志记录。如果调用方从未订阅返回的发布服务器,则实际上可能是不正确的。发布者也可能被多次调用,比如在重试或重复等情况下,这也将是错误的

在第二种情况下,它将在每次订阅时调用

public class Foo {

    static Mono<String> echo(String message) {
        System.out.println("echo called with " + message);
        return Mono.just(message);
    }

    static Mono<String> rxEcho(String message) {
        return Mono.just(message).doOnNext(msg -> System.out.println("rxEcho was called with " + msg));
    }

    public static void main(String[] args) {
        //logged, even though never actually called
        echo("no sub");
        //only logs 1 time
        echo("retry")
            .repeat(3)
            .blockLast();

        System.out.println("---------------");

        //never subbed, never logged
        rxEcho("no sub");

        //all 4 calls are logged
        rxEcho("retry")
            .repeat(3)
            .blockLast();
    }
}
公共类Foo{
静态单声道回波(字符串消息){
System.out.println(“用“+消息调用的echo”);
返回Mono.just(消息);
}
静态单声道rxEcho(字符串消息){
返回Mono.just(message.doOnNext(msg->System.out.println(“用“+msg”调用rxEcho));
}
公共静态void main(字符串[]args){
//已登录,即使从未实际调用
echo(“无子公司”);
//只记录1次
回显(“重试”)
.重复(3)
.blockLast();
System.out.println(“--------------”;
//从不下床,从不记录
rxEcho(“无子公司”);
//所有4个电话都记录在案
rxEcho(“重试”)
.重复(3)
.blockLast();
}
}

还要注意的是,在实际代码中不应该调用任何block()风格,我不想将示例与StepVerifier混淆。

但是,在webclient调用中添加显式日志作为步骤是我试图避免的。我宁愿使用全局记录器一次性配置webclient,然后在任何webcall上都不必关心日志记录,因为它是自动应用的。类似于
restemplate
s如何配置用于日志记录的拦截器。您认为您的代码在做什么?进一步阅读baeldung的文章,你会看到许多其他的可能性。然后还有其他的可能性。实际上有区别,请看我的答案。这很好,但离题了。我认为如果没有订阅,网络客户端根本不会被调用。你错了。它很可能在.switchIfEmpty()中调用,但从未订阅,因为另一个发布服务器发出一个值。我总是这样做。关键是你不(也不应该)知道出版商是如何使用的。您需要在订阅上执行操作,而不是调用。