SpringCloud gateway如何修改返回数据

版本说明

开源软件 版本
springboot 2.1.6.RELEASE
jdk 11.0.3

gradle

主要引入了springboot 2.1,lombok

plugins {
    id 'org.springframework.boot' version '2.1.6.RELEASE'
    id 'java'
    id "io.freefair.lombok" version "3.6.6"
}apply plugin: 'io.spring.dependency-management'group = 'cn.buddie.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'repositories {
    mavenCentral()
}ext {
    set('springCloudVersion', "Greenwich.SR2")
}dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    compile 'org.projectlombok:lombok:1.18.8'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

yaml

定义路由及过滤器 test-route路由,当Path为/users时,转到uri中配置的链接http://127.0.0.1:8123/users中。使用UnionResult来过滤

spring:
  cloud:
    gateway:
      enabled: true
      routes:
      - id: test-route
        uri: http://127.0.0.1:8123/users
        predicates:
        - Path=/users
        filters:
        - UnionResult

filter

yaml中配置的filter名字,加“GatewayFilterFactory”,就是对应的过滤器Java类

package cn.buddie.demo.springcloudgateway.filter;import cn.buddie.demo.springcloudgateway.model.UnionResult;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;/**
 * description
 *
 * @author buddie.wei
 * @date 2019/7/20
 */
@Component
public class UnionResultGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {
    @Override
    public GatewayFilter apply(Config config) {
        return new ModifyResponseGatewayFilter(this.getConfig());
    }
    private Config getConfig() {
        Config cf = new Config();
        // Config.setRewriteFunction(Class<T> inClass, Class<R> outClass, RewriteFunction<T, R> rewriteFunction)
        // inClass 原数据类型,可以指定为具体数据类型,我这里指定为Object,是为了处理多种数据类型。
        //                      当然支持多接口返回多数据类型的统一修改,yaml中的配置,path,uri需要做相关调整
        // outClass 目标数据类型
        // rewriteFunction 内容重写方法
        cf.setRewriteFunction(Object.class, UnionResult.class, getRewriteFunction());
        return cf;
    }    private RewriteFunction<Object, UnionResult> getRewriteFunction() {
        return (exchange, resp) -> Mono.just(UnionResult.builder().requestId(exchange.getRequest().getHeaders().getFirst("cn-buddie.demo.requestId")).result(resp).build());
    }
}

model

package cn.buddie.demo.springcloudgateway.model;import lombok.Builder;
import lombok.Getter;
import lombok.Setter;/**
 * description
 *
 * @author buddie.wei
 * @date 2019/7/20
 */
@Getter
@Setter
@Builder
public class UnionResult {
    private String requestId;
    private Object result;
}

SpringCloud gateway修改返回的响应体

问题描述:

在gateway中修改返回的响应体,在全局Filter中添加如下代码:

import org.springframework.core.Ordered;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
public class RequestGlobalFilter implements GlobalFilter, Ordered {
 //...

 @Override
 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  //...
  ResponseDecorator decorator = new ResponseDecorator(exchange.getResponse());
  return chain.filter(exchange.mutate().response(decorator).build());
 } @Override
 public int getOrder() {
  return -1000;
 }
}

通过.response(decorator)设置一个响应装饰器(自定义),以下是装饰器具体实现:

import cn.hutool.json.JSONObject;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;/**
 * @author visy.wang
 * @desc 响应装饰器(重构响应体)
 */
public class ResponseDecorator extends ServerHttpResponseDecorator{
 public ResponseDecorator(ServerHttpResponse delegate){
  super(delegate);
 } @Override
 @SuppressWarnings(value = "unchecked")
 public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {  if(body instanceof Flux) {
   Flux<DataBuffer> fluxBody = (Flux<DataBuffer>) body;   return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
    DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
    DataBuffer join = dataBufferFactory.join(dataBuffers);    byte[] content = new byte[join.readableByteCount()];
    join.read(content);
    DataBufferUtils.release(join);// 释放掉内存

    String bodyStr = new String(content, Charset.forName("UTF-8"));                //修改响应体
    bodyStr = modifyBody(bodyStr);    getDelegate().getHeaders().setContentLength(bodyStr.getBytes().length);
    return bufferFactory().wrap(bodyStr.getBytes());
   }));
  }
  return super.writeWith(body);
 }    //重写这个函数即可
 private String modifyBody(String jsonStr){
  JSONObject json = new JSONObject(jsonStr);
        //TODO...修改响应体
  return json.toString();
 }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring Cloud Gateway(读取、修改 Request Body)的操作

    Spring Cloud Gateway(以下简称 SCG)做为网关服务,是其他各服务对外中转站,通过 SCG 进行请求转发. 在请求到达真正的微服务之前,我们可以在这里做一些预处理,比如:来源合法性检测,权限校验,反爬虫之类- 因为业务需要,我们的服务的请求参数都是经过加密的. 之前是在各个微服务的拦截器里对来解密验证的,现在既然有了网关,自然而然想把这一步骤放到网关层来统一解决. 如果是使用普通的 Web 编程中(比如用 Zuul),这本就是一个 pre filter 的事儿,把之前 Int

  • zuulGateway 通过filter统一修改返回值的操作

    使用spring cloud有时候我们给客户端返回内容的时候,往往需要添加一些额外的东西.比如加密,多添加一个返回值等等. 当然可以在方法里面处理,但如果方法很多,需要统一处理的,就很不方便了,这时候可以通过zuulGateway的filter来统一处理. 直接看代码,很简单: import java.io.InputStream; import java.nio.charset.Charset; import org.springframework.cloud.netflix.zuul.fil

  • 解决spring cloud gateway 获取body内容并修改的问题

    之前写过一篇文章,如何获取body的内容. Spring Cloud Gateway获取body内容,不影响GET请求 确实能够获取所有body的内容了,不过今天终端同学调试接口的时候和我说,遇到了400的问题,报错是这样的HTTP method names must be tokens,搜了一下,都是说https引起的.可我的项目还没用https,排除了. 想到是不是因为修改了body内容导致的问题,试着不修改body的内容,直接传给微服务,果然没有报错了. 问题找到,那就好办了,肯定是我新构

  • Spring Cloud Gateway 记录请求应答数据日志操作

    我就废话不多说了,大家还是直接看代码吧~ public class GatewayContext { public static final String CACHE_GATEWAY_CONTEXT = "cacheGatewayContext"; /** * cache json body */ private String cacheBody; /** * cache formdata */ private MultiValueMap<String, String> f

  • SpringCloud gateway如何修改返回数据

    版本说明 开源软件 版本 springboot 2.1.6.RELEASE jdk 11.0.3 gradle 主要引入了springboot 2.1,lombok plugins { id 'org.springframework.boot' version '2.1.6.RELEASE' id 'java' id "io.freefair.lombok" version "3.6.6" }apply plugin: 'io.spring.dependency-m

  • Spring Cloud Gateway 如何修改HTTP响应信息

    Gateway 修改HTTP响应信息 实践Spring Cloud的过程中,使用Gateway作为路由组件,并且基于Gateway实现权限的验证.拦截.过滤,对于下游微服务的响应结果,我们总会有需要修改以统一数据格式,或者修改过滤用户没有权限看到的数据信息,这时候就需要有一个能够修改响应体的Filter. Spring Cloud Gateway 版本为2.1.0 在当前版本,ModifyRequestBodyGatewayFilterFactory是官方提供的修改响应体的参考类,This fi

  • SpringCloud gateway request的body验证或修改方式

    SpringCloud gateway request的body验证或修改 后续版本新增了以下过滤器 org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter 默认会把以下头部移除(暂不了解这做法的目的) - connection - keep-alive - te - transfer-encoding - trailer - proxy-authorization - proxy-authenti

  • 基于Fiddler实现修改接口返回数据进行测试

    方法介绍与比对 在测试的过程中,有的需求是这样的,它需要你修改接口返回的数据,从而检查在客户端手机app内是否显示正确,这也算是一种接口容错测试,接口容错测试属于app性能(专项)测试的其中一种. 通过Fiddler我们可以有好几种方法修改返回结果: 第一种:在Fiddler底部的黑色命令行显示区域通过bpu url的形式按回车之后进行拦截,通过手机app访问指定接口,拦截到后可以选择response文件后通过拦截: 第二种:在AutoRespnder里Add Rule,然后在Rule Edit

  • SpringCloud Gateway自定义filter获取body中的数据为空的问题

    最近在使用SpringCloud Gateway进行网关的开发,我使用的版本是:SpringBoot的2.3.4.RELEASE+SpringCloud的Hoxton.SR8,在自定义过滤器时需要获取ServerHttpRequest中body的数据,发现一直无法获取到数据,经过各种百度.谷歌,再加上自己的实践,终于找到解决方案: 1.首先创建一个全局过滤器把body中的数据缓存起来 package com.cloudpath.gateway.portal.filter; import lomb

  • springcloud gateway聚合swagger2的方法示例

    问题描述 在搭建分布式应用时,每个应用通过nacos在网关出装配了路由,我们希望网关也可以将所有的应用的swagger界面聚合起来.这样前端开发的时候只需要访问网关的swagger就可以,而不用访问每个应用的swagger. 框架 springcloud+gateway+nacos+swagger 问题分析 swagger页面是一个单页面应用,所有的显示的数据都是通过和springfox.documentation.swagger.web.ApiResponseController进行数据交互,

  • 浅谈springcloud gateway 连接保活问题

    项目中使用了springcloud gateway作为网关,上游与负载均衡服务器连接. 近期通过监控系统观察,发现网关与上游负载均衡服务器保持的TCP连接有300+,初步怀疑是调用方未释放连接 用如下方法进行分析: 1)周期性采集当前建立的连接及端口数据 首先是每隔10分钟连续采集2两个小时,发现在两个小时之内新出现的端口不到12个,再逐步缩短采样周期,到最后每秒采集一次,分析发现每秒种建立一个连接,同时关闭一个连接,当仍存在300+连接,这些连接对应的端口称为不活跃端口,记录下这300+不活跃

  • SpringCloud Gateway的基本入门和注意点详解

    目录 1.gateway和zuul 2.使用gateway的路由功能 1. 搭载springcloud gateway 2.简单使用gateway 1.application配置 1.gateway和zuul Spring Cloud Finchley版本的gateway比zuul 1.x系列的性能和功能整体要好,且使用 Gateway 做跨域相比应用本身或是 Nginx 的好处是规则可以配置的更加灵活. 这两者相同的地方就是都是作为网关,处理前段的请求,可以进行路由到对应的服务或者url,也可

  • SpringCloud Gateway网关功能介绍与使用

    目录 一.什么是API网关 二.基本使用 三.谓词 四.过滤器-Filter 五.使用Gateway实现限流 六.使用Gateway实现服务降级 七.自定义全局过滤器 八.自定义路由过滤器 一.什么是API网关 API网关作用就是把各个服务对外提供的API汇聚起来,让外界看起来是一个统一的接口.同时也可在网关中提供额外的功能. 总结:网关就是所有项目的一个统一入口. 二.基本使用 1.准备Eureka注册中心 2.准备一个微服务工程 3.搭建Gateway网关微服务 (1)导入依赖 <depen

随机推荐