• 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来替换原先的request

            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构建完成之后需要在拦截器中使用如下方法替换原先的request

                        return chain.filter(exchange.mutate().request(decorator).build());
    
    
    SpringCloudGateway中如何读取后段服务的返回数据

    与上方替换request的思路一致,替换response即可

    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,获取到新的之后和之前的套路一样,这样操作:

                        return chain.filter(exchange.mutate().request(decorator).response(decoratedResponse).build());
    

    可能有的同学会碰到即使按照我上述的方法重写了response但是也无法读取到返回数据,这个原因可能是因为拦截器的优先级配置有问题,只需要实现Ordered接口并且重写getOrder方法,然后设置优先级小于-1即可

    @Override
        public int getOrder() {
            return -2;
        }
    

    原文地址

  • 相关阅读:
    入门5查询生成器
    入门4关键概念
    入门3请求处理
    入门2应用结构
    入门1-基础入门
    PHP代码规范
    Bug总结
    数据结构与常用集合总结
    CSS之使用display:inline-block来布局
    nginx,lvs,haproxy+keepalived区别
  • 原文地址:https://www.cnblogs.com/zhixiang-org-cn/p/11946886.html
Copyright © 2020-2023  润新知