springcloud gateway 业务系统返回的响应报文内容分段传输导致不全的解决方案

springcloud 专栏收录该内容
10 篇文章 0 订阅

1.我们在实际开发中由网关路由到业务系统处理后返回响应报文。对于返回小内容响应报文通过super.writeWith(fluxBody.map(dataBuffer -> {}))是没有问题的,
但有时业务系统需要返回过大的响应报文的时候就有问题了,fluxBody返回体会存在分段传输,从而导致返回的json报文只有一半,前端无法解析而导致错误。

解决方案如下:
既然返回内容过大存在分段传出,比如json传输了一半,另一半丢失,所以我们需要考虑报文拼装方式,只有报文全部返回才统一返回给前端。
大报文我们需要对fluxBody流循环拼接处理,所以改变方式如下,把fluxBody.map变为fluxBody.buffer().map,从而可以foreach循环Body体了。

代码如下:

public class WrapperResFilter implements GlobalFilter, Ordered {
    
    private static Joiner joiner = Joiner.on("");//将 List 数据以""分隔进行拼接

    @Override
    public int getOrder() {
        return -10;
    }
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取response的 返回数据
        ServerHttpResponse originalResponse = exchange.getResponse();
        HttpHeaders header = originalResponse.getHeaders();
        header.add("Content-Type", "application/json; charset=UTF-8");
        
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                log.info("body:{},getStatusCode():{}",body,getStatusCode());
                if (getStatusCode() != null && getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {//解决返回体分段传输
                        List<String> list = Lists.newArrayList();
                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            try {
                                list.add(new String(content, "utf-8"));
                            } catch (Exception e) {
                                log.error("--list.add--error",e);
                            }
                        });
                        String responseData = joiner.join(list);                  
                        String resStr = CommonMethod.resSetResult(responseData);
                        byte[] uppedContent = new String(resStr.getBytes(), Charset.forName("UTF-8")).getBytes();
                        originalResponse.getHeaders().setContentLength(uppedContent.length);
                        return bufferFactory.wrap(uppedContent);

                    }));

              以下省略...

  • 7
    点赞
  • 11
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值