SpringCloud Gateway拦截器遇到的小坑汇总

喜夏-厌秋 提交于 2019-11-29 06:02:32

很多朋友在使用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;     } 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!