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)