簡體   English   中英

Spring WebFlux-WebFilter中的statusCode為null

[英]Spring WebFlux - statusCode is null in a WebFilter

當前使用Spring Boot 2.0.4開發的WebFilter在Spring WebFlux應用程序中記錄HTTP請求和響應信息(URL,響應狀態代碼,持續時間等)。

exchange.getResponse()。getStatusCode()保持為null之外,其他方法均能正常工作

嘗試了兩個不同的過濾器(ServerWebExchange交換,WebFilterChain鏈) ,第一個:

return chain.filter(exchange).doAfterTerminate(
        () -> System.out.println("Status=" + exchange.getResponse().getStatusCode()));

第二個:

    Mono<Void> filtered = chain.filter(exchange);
    exchange.getResponse().beforeCommit(() -> {
        System.out.println("Status=" + exchange.getResponse().getStatusCode());
        return Mono.empty();
    });
    return filtered;

還嘗試了過濾器上的各種訂單:無,@ Order(100000),@ Order(-100000)。

狀態代碼保持為空。

什么是正確的實現?

更新1

編寫了一個基於KevH解決方案的簡約工作示例,請參閱https://github.com/fbeaufume/webflux-filter-sample,但它仍無法正常工作,狀態仍然為null。 MWE公開了兩個REST端點:/ hello和/ pause / 1000(暫停1秒)。

請注意,當調用暫停端點日志時:

11:06:20.644  INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.LogFilter           : Request [/pause/1000] started, traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:20.673  INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.HelloController     : Pausing for 1000 msec
11:06:21.683  INFO 9536 --- [     parallel-2] com.adeliosys.sample.LogFilter           : Request [/pause/1000] completed, statusCode [null], time [1039], traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:21.684  INFO 9536 --- [     parallel-2] com.adeliosys.sample.HelloController     : Paused for 1000 msec

我很驚訝過濾器的第二條消息顯示端點的第二條消息之前

更新2

看來使用doAfterTerminate(或類似方法)的過濾器實現是正確的,但這只能使用在返回類型中使用ResponseEntity的 REST控制器方法來正確檢索HTTP響應狀態。

不支持(即狀態為null): voidMono<Void>StringMono<String>MyBeanMono<MyBean>等。

支持(即狀態為200): ReponseEntity<Void>Mono<ResponseEntity<Void>>ReponseEntity<String>Mono<ResponseEntity<String>>ReponseEntity<MyBean>Mono<ResponseEntity<MyBean>>等。

錯誤?

Spring Boot 2.0.5具有相同的行為。

更新3

打開了關於該主題的問題,請參閱https://jira.spring.io/browse/SPR-17368

您可以嘗試doAfterSuccessOrError

@Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String traceId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();
        String path = exchange.getRequest().getURI().getPath();
        System.out.printf("Request[%s] started, trace_id[%s]", path, traceId);

        return chain.filter(exchange)
                .doAfterSuccessOrError((r, t) -> {
                    System.out.printf("Request[%s], completed, status_code[%s], time[%d], trace_id[%s]", path,
                            exchange.getResponse().getStatusCode(), System.currentTimeMillis() - startTime, traceId);
                })
                .subscriberContext(Context.of(String.class, traceId));
    }

樣本輸出

請求[/ logrequest]已開始,trace_id [b45b550a-b9ad-4323-a850-cb085a78a086]請求[/ logrequest],已完成,狀態碼[202],時間[41],trace_id [b45b550a-b9ad-4323-a850-cb085a78a086]

編輯:不確定為什么這不起作用,但是這兩個解決方法都有一個ResponseEntity

@GetMapping("/hello")
    public Mono<ResponseEntity<String>> publicHello() {
        return Mono.just(ResponseEntity.ok("Hello world!"));
    }

    @GetMapping("/pause/{duration}")
    @ResponseStatus(HttpStatus.ACCEPTED)
    public Mono<Void> pause2(@PathVariable long duration) {
        LOGGER.info("Pausing for {} msec", duration);
        return (duration > 0 ? Mono.delay(Duration.ofMillis(duration)) : Mono.empty())
                .then()
                .doFinally(s -> LOGGER.info("Paused for {} msec", duration));
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM