好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringCloud gateway如何修改返回数据

版本说明

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

gradle

主要引入了springboot 2.1,lombok

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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来过滤

?

1

2

3

4

5

6

7

8

9

10

11

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类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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中添加如下代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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)设置一个响应装饰器(自定义),以下是装饰器具体实现:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

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();

  }

}

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

原文链接:https://my.oschina.net/buddie/blog/3076723

查看更多关于SpringCloud gateway如何修改返回数据的详细内容...

  阅读:22次