真的是翻了很多文章,都没有达到效果
不说废话直接干货
定义BodyRewrite 用来接收spring的回调信息
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class BodyRewrite implements RewriteFunction<byte[], byte[]> {
@Override
public Publisher<byte[]> apply(ServerWebExchange exchange, byte[] body) {
String originalBody = body==null?"":new String(body);
if (StringUtils.isEmpty(originalBody)) {
return Mono.empty();
} else {
exchange.getAttributes().put("body", originalBody);
return Mono.just(originalBody.getBytes());
}
}
}
上图拿到 originalBody 就是用户请求的信息,将其放进attributes方便后面随时获取
定义全局过滤将BodyRewrite 放进spring中
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class ModifyResponseBodyFilter implements GlobalFilter, Ordered {
@Autowired
private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory;
@Autowired
private BodyRewrite bodyRewrite;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
GatewayFilter delegate = modifyRequestBodyGatewayFilterFactory.apply(new ModifyRequestBodyGatewayFilterFactory.Config()
.setRewriteFunction(byte[].class, byte[].class, bodyRewrite));
return delegate.filter(exchange, chain);
}
@Override
public int getOrder() {
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1;
}
}
历经千辛万苦终于找到了方法,
参考地址
https://stackoverflow.com/questions/64439102/how-to-get-response-body-in-spring-gateway/64458684#
以上是关键代码,至于请求方式 content_type请求类型等校验什么时候加载获取body的业务代码根据场景自行补充
第二种
public class ModifyResponseBodyFilter implements GlobalFilter, Ordered {
@Value("#{'${gateway.response.body.exclude.uri:}'.split(',')}")
private List<String> excludeUris;
@Value("#{'${gateway.response.body.flag:true}'}")
private boolean responseFlag;
@Autowired
private IRequestLogService requestLogService;
@Override
public int getOrder() {
// 必须要小于 -1
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!responseFlag) {
// 关闭获取响应信息
return chain.filter(exchange);
}
String url = exchange.getRequest().getPath().pathWithinApplication().value();
if (excludeUris.contains(url)) {
return chain.filter(exchange);
}
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
// 获取响应 ContentType
String responseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
if (!StringUtils.isEmpty(responseContentType) &&
(responseContentType.contains(MediaType.APPLICATION_JSON_VALUE)
|| responseContentType.contains(MediaType.TEXT_PLAIN_VALUE))) {
Flux<? extends DataBuffer> fluxBody = Flux.from(body);
return super.writeWith(fluxBody.buffer().map(dataBuffer -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer buffer= dataBufferFactory.join(dataBuffer);
byte[] content = new byte[buffer.readableByteCount()];
buffer.read(content);
//释放掉内存
DataBufferUtils.release(buffer);
String s = new String(content, StandardCharsets.UTF_8);
return bufferFactory.wrap(s.getBytes());
}));
}
}
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}