Spring webflux - код ServerWebExchangeDecorator не выполняется при возникновении исключения - PullRequest
0 голосов
/ 14 января 2020

У меня есть приложение Webflux, где у меня есть ServerWebExchangeDecorator, который украшает запрос и ответы. У меня есть переопределения, чтобы сделать некоторые записи, а затем вызвать супер методы. Это то, что у меня есть в коде:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Component
public class LoggingWebFilter implements WebFilter {

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(decorate(exchange));
  }

  private ServerWebExchange decorate(ServerWebExchange exchange) {

    final ServerHttpRequest decoratedRequest = new LoggingServerHttpRequestDecorator(exchange.getRequest());
    final ServerHttpResponse decoratedResponse = new LoggingServerHttpResponseDecorator(exchange.getResponse());

    return new ServerWebExchangeDecorator(exchange) {

      @Override
      public ServerHttpRequest getRequest() {
        return decoratedRequest;
      }

      @Override
      public ServerHttpResponse getResponse() {
        return decoratedResponse;
      }

    };
  }

}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import reactor.core.publisher.Flux;

public class LoggingServerHttpRequestDecorator extends ServerHttpRequestDecorator {

  private static final Logger logger = LoggerFactory.getLogger(LoggingServerHttpRequestDecorator.class);

  public LoggingServerHttpRequestDecorator(ServerHttpRequest delegate) {
    super(delegate);
  }

  @Override
  public Flux<DataBuffer> getBody() {
    logger.info("getBody method");
    return super.getBody();
  }

}
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Mono;

public class LoggingServerHttpResponseDecorator extends ServerHttpResponseDecorator {

  private static final Logger logger = LoggerFactory.getLogger(LoggingServerHttpResponseDecorator.class);

  public LoggingServerHttpResponseDecorator(ServerHttpResponse delegate) {
    super(delegate);
  }

  @Override
  public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
    logger.info("writeWith method");//THIS LINE IS NOT EXECUTED WHEN AN EXCEPTION IS THROWN
    return super.writeWith(body);
  }

  @Override
  public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
    logger.info("writeAndFlushWith method");
    return super.writeAndFlushWith(body);
  }

}

Когда я делаю счастливый путь с запросом POST, это работает нормально, но когда выдается исключение, декоратор ответа опускается и мой пользовательский код не выполняется.

Это код контроллера для репликации проблемы:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/decorator-demo")
public class DecoratorDemoController {

  /** The Constant logger. */
  private static final Logger logger = LoggerFactory.getLogger(DecoratorDemoController.class);


  @PostMapping(produces = MediaType.APPLICATION_STREAM_JSON_VALUE, consumes = MediaType.APPLICATION_STREAM_JSON_VALUE)
  public Mono<ResponseEntity<String>> postData(@RequestBody String id) {
    logger.info("attempting to post the data");
    if(id.length() == 1){
      Mono<String> created = Mono.just(id);
      return created.flatMap(vo -> Mono.just(ResponseEntity.status(HttpStatus.CREATED).body(vo)));
    }
    throw new IllegalArgumentException("String length must be 1");
  }

}

Когда я публикую один символ, у меня есть журналы, которые я ожидаю:

LoggingServerHttpRequestDecorator  : getBody method
DecoratorDemoController            : attempting to post the data
LoggingServerHttpResponseDecorator : writeWith method

Но когда я публикую более одного символа, у меня появляются журналы:

LoggingServerHttpRequestDecorator  : getBody method
DecoratorDemoController            : attempting to post the data
AbstractErrorWebExceptionHandler : [0b933716]  500 Server Error for HTTP POST "/decorator-demo"

Я что-то делаю не так или что-то не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...