SpringCloud Gateway攔截器遇到的小坑彙總

不少朋友在使用SpringCloudGateway的時候可能都碰到過如下幾個問題後端

SpringCloudGateway中如何讀取Post請求體
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;
    }
SpringCloudGateway中Post請求參數只能讀取一次

這是由於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());
SpringCloudGateway中如何讀取後段服務的返回數據

與上方替換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;
    }

1

相關文章
相關標籤/搜索