不少朋友在使用SpringCloudGateway的時候可能都碰到過如下幾個問題後端
private BodyInserter getBodyInserter(ServerWebExchange exchange) { ServerRequest serverRequest = new DefaultServerRequest(exchange); Mono<String> modifiedBody = serverRequest.bodyToMono(String.class) .flatMap(body -> { //這裏的body就是Post的請求體 }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class); return bodyInserter; }
這是由於Gateway默認使用的是SpringWebflux,解決這個問題須要容從新構造一個request來替換原先的requestide
HttpHeaders headers=new HttpHeaders(); CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); ServerHttpRequestDecorator decorator = this.getServerHttpRequestDecorator(exchange,outputMessage); ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator( exchange.getRequest()) { @Override public Flux<DataBuffer> getBody() { return outputMessage.getBody(); } };
當ServerHttpRequestDecorator構建完成以後須要在攔截器中使用以下方法替換原先的requestui
return chain.filter(exchange.mutate().request(decorator).build());
與上方替換request的思路一致,替換response便可this
private ServerHttpResponse getServerHttpResponse(ServerWebExchange exchange) { ServerHttpResponse originalResponse = exchange.getResponse(); DataBufferFactory bufferFactory = originalResponse.bufferFactory(); ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { Flux<DataBuffer> flux = null; if (body instanceof Mono) { Mono<? extends DataBuffer> mono = (Mono<? extends DataBuffer>) body; body = mono.flux(); } if (body instanceof Flux) { flux = (Flux<DataBuffer>) body; return super.writeWith(flux.buffer().map(dataBuffers -> { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); dataBuffers.forEach(i -> { byte[] array = new byte[i.readableByteCount()]; i.read(array); DataBufferUtils.release(i); outputStream.write(array, 0, array.length); }); String result = outputStream.toString(); try { if (outputStream != null) { outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } log.info("後端返回數據:{}", result); return bufferFactory.wrap(result.getBytes()); })); } log.info("降級處理返回數據:{}" + body); return super.writeWith(body); } }; return decoratedResponse; }
上方是獲取新的response,獲取到新的以後和以前的套路同樣,這樣操做:code
return chain.filter(exchange.mutate().request(decorator).response(decoratedResponse).build());
可能有的同窗會碰到即便按照我上述的方法重寫了response可是也沒法讀取到返回數據,這個緣由多是由於攔截器的優先級配置有問題,只須要實現Ordered接口而且重寫getOrder方法,而後設置優先級小於-1便可server
@Override public int getOrder() { return -2; }