>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring》、《Spring Cloud Alibaba微服务开发零基础入门到实操》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 27912 个阅读者 刷新本主题
 * 贴子主题:  SpringCloud Gateway拦截器遇到的小坑汇总 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-01-07 00:28:37     消息  查看  搜索  好友  邮件  复制  引用

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

----------------------------
原文链接:https://www.jianshu.com/p/f80118fb004b



[这个贴子最后由 flybird 在 2020-01-07 18:37:39 重新编辑]
  Java面向对象编程-->图形用户界面(上)
  JavaWeb开发-->变量的作用域和初始化
  JSP与Hibernate开发-->JSP技术详解(Ⅱ)
  Java网络编程-->Web运作原理(Ⅲ)
  精通Spring-->数据库事务的并发问题的解决方案
  Vue3开发-->映射一对多关联关系
  10分钟认识RocketMQ!想进阿里连这个都不会?
  MyBatis+Spring 事务管理
  循序渐进,阿里架构师看完都赞叹的Redis分布式锁原理分析
  @Configuration注解的用法
  使用Spring MVC处理404错误的方法
  【项目实践】后端接口统一规范的同时,如何优雅地扩展规范
  Spring Boot 基于 JUnit 5 实现单元测试
  @SessionAttributes的用法
  什么是Redis?Redis的各项功能解决了哪些问题?
  Spring Cloud与Dubbo的完美融合之手「Spring Cloud Alibaba
  Java软件架构设计七大原则
  Spring Boot整合WebSocket及Spring Security实例
  什么是CXF
  MyBatis解析和运行原理
  大话微服务」深入聊聊SpringCloud之客户端负载均衡机制
  更多...
 IPIP: 已设置保密
楼主      
该用户目前不在线 nihaota 
  
威望: 0
级别: 新手上路
魅力: 1315
经验: 1315
现金: 2944
发文章数: 243
注册时间: 0001-01-01
 消息  查看  搜索  好友  邮件  复制  引用


讨债公司
发文章时间 2022-10-28 20:38:05
 IPIP: 已设置保密 1 楼     
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。