`

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

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;    }

 

 

本文完整源码地址点击阅读原文地址获取

往期好文

阅读源码的小技巧 

SpringBoot源码解析系列汇总

Spring源码解析系列汇总

Eureka源码解析系列汇总

SpringCloud服务调用源码解析汇总

RabbitMQ系列汇总

SpringCloud基础系列汇总

Redis系列汇总

MySQL系列汇总

1

0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics