2022-11-01

在Spring Cloud Gateway使用编码的方式实现一个全局拦截器,在全局拦截器中想要打印响应日志。


于是自己装饰了一个具有打印日志功能的ServerHttpResponseDecorator,但是在转发后的服务返回响应的时候,ServerHttpResponseDecorator的writeWith却并没有执行

@Component

@Slf4j

public class CustomGlobaFilter implements GlobalFilter, Ordered {


    @Override

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //响应日志

        return handleResponse(exchange, chain);

    }


    public Mono<Void> handleResponse(ServerWebExchange exchange, GatewayFilterChain chain) {

        try {

            ServerHttpResponse originalResponse = exchange.getResponse();

            // 缓存数据的工厂

            DataBufferFactory bufferFactory = originalResponse.bufferFactory();

            // 拿到响应码

            HttpStatus statusCode = originalResponse.getStatusCode();

            if (statusCode == HttpStatus.OK) {

                // 装饰,增强能力

                ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {

                    // 等调用完转发的接口后才会执行

                    @Override

                    public Mono<Void>  writeWith(Publisher<? extends DataBuffer> body) {

                        log.info("body instanceof Flux: {}", (body instanceof Flux));

                        if (body instanceof Flux) {

                            Flux<? extends DataBuffer> fluxBody = Flux.from(body);

                            // 往返回值里写数据

                            // 拼接字符串

                            return super.writeWith(

                                    fluxBody.map(dataBuffer -> {

                                        byte[] content = new byte[dataBuffer.readableByteCount()];

                                        dataBuffer.read(content);

                                        //释放掉内存

                                        DataBufferUtils.release(dataBuffer);

                                        // 构建日志

                                        StringBuilder sb2 = new StringBuilder(200);

                                        List<Object> rspArgs = new ArrayList<>();

                                        rspArgs.add(originalResponse.getStatusCode());

                                        //data

                                        String data = new String(content, StandardCharsets.UTF_8); 

                                        sb2.append(data);

                                        // 打印日志

                                        log.info("响应结果:" + data);

                                        return bufferFactory.wrap(content);

                                    }));

                        } else {

                            // 8. 调用失败,返回一个规范的错误码

                            log.error("<--- {} 响应code异常", getStatusCode());

                        }

                        return super.writeWith(body);

                    }

                };

                // 设置 response 对象为装饰过的

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

            }

            // 降级处理返回数据

            return chain.filter(exchange); 

        } catch (Exception e) {

            log.error("网关处理响应异常" + e);

            return chain.filter(exchange);

        }

    }


    @Override

    public int getOrder() {

        return 0;

    }

}

将getOrder方法的返回值设置为-2

@Override

public int getOrder() {

    return -2;

}