博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring cloud gateway 源码解析(3)记录请求参数及返回的json
阅读量:6180 次
发布时间:2019-06-21

本文共 5047 字,大约阅读时间需要 16 分钟。

(1)一开始搜索读取参数的文章,方法大多是从body里读一次DataBuffer,转成字符串,然后再把字符串转成DataBuffer重新放到body里,如:

(2)

上面的方法我试过可以,但是Content-Type是multipart/form-data的时候会报错java.lang.IllegalStateException: Only one connection receive subscriber allowed.不知道是不是我姿势不对。而且如果我们在代理到第三方服务的时候才读取body,这样效率应该会高一些看NettyRoutingFilter类里的filter方法public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) { ······· Mono
responseMono = this.httpClient.request(method, url, req -> { final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach) .headers(httpHeaders) .chunkedTransfer(chunkedTransfer) .failOnServerError(false) .failOnClientError(false); if (preserveHost) { String host = request.getHeaders().getFirst(HttpHeaders.HOST); proxyRequest.header(HttpHeaders.HOST, host); } if (properties.getResponseTimeout() != null) { proxyRequest.context(ctx -> ctx.addHandlerFirst( new ReadTimeoutHandler(properties.getResponseTimeout().toMillis(), TimeUnit.MILLISECONDS))); } return proxyRequest.sendHeaders() //这里的是ReactorServerHttpRequest调用了getBody()方法, //所以我们只要重写ReactorServerHttpRequest的getbody方法,加上我们读取的逻辑就行了, //gateway给我们提供了装饰类ServerHttpRequestDecorator,我们只需把过滤器的优先级设置高于NettyRoutingFilter(实际他已经是倒数第二的优先级了),且把ReactorServerHttpRequest替换成ServerHttpRequestDecorator就行了 .send(request.getBody().map(dataBuffer -> ((NettyDataBuffer) dataBuffer).getNativeBuffer())); });给个stackoverflow的伪代码ServerHttpRequestDecorator decoratedRequest = new ServerHttpRequestDecorator(request) { @Override public Flux
getBody() { StringBuilder sb=new StringBuilder(); return super.getBody().map(dataBuffer -> { // probably should reuse buffers byte[] content = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(content); byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes(); return bufferFactory.wrap(uppedContent); }) ; }}; //再说说记录返回的json,在NettyRoutingFilter类的154行,请求第三方服务反回后, // Defer committing the response until all route filters have run // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter //注释说了把返回结果放进ServerWebExchange 的参数里了,并且在NettyWriteResponseFilter读取 exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);看NettyWriteResponseFilter的读取代码,public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange).then(Mono.defer(() -> { //拿出NettyRoutingFilter放进去的Response HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); if (clientResponse == null) {//空的就不过直接到下一个过滤器 return Mono.empty(); } log.trace("NettyWriteResponseFilter start"); ServerHttpResponse response = exchange.getResponse(); NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory(); //TODO: what if it's not netty final Flux
body = clientResponse.receive() .retain() //TODO: needed? .map(factory::wrap); MediaType contentType = null; try { contentType = response.getHeaders().getContentType(); } catch (Exception e) { log.trace("invalid media type", e); } //判断contentType是不是text/event-stream或者application/stream+json //反正上面两种类型的结果我们肯定不用记录,所以我们重写response的writeWith方法就好, //跟上面一样gateway也提供了个装饰器类ServerHttpResponseDecorator return (isStreamingMediaType(contentType) ? response.writeAndFlushWith(body.map(Flux::just)) : response.writeWith(body)); })); }上stackoverflow的伪代码DataBufferFactory bufferFactory = originalResponse.bufferFactory(); ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { @Override public Mono
writeWith(Publisher
body) { if (body instanceof Flux) { Flux
fluxBody = (Flux
) body; return super.writeWith(fluxBody.map(dataBuffer -> { // probably should reuse buffers byte[] content = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(content); byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes(); return bufferFactory.wrap(uppedContent); })); } return super.writeWith(body); // if body is not a flux. never got there. } };

参考:

该如果返回的数据长度很长的话,数据可能会读不完全,如果出现读取时截取了中文字符,导致长度变多1位,进而json的右括号消失,也可参考下面链接

参考解决方案:

转载地址:http://mbdda.baihongyu.com/

你可能感兴趣的文章
懒汉式单例
查看>>
java递归组装树形结构
查看>>
手把手教你自己写一个模糊搜索的下拉框
查看>>
.Net文档图像处理工具包GdPicture.NET发布v14.0.30,改进PDF/OCR生成速度
查看>>
NetBSD 8.1 RC1 发布
查看>>
PHP FPM源代码反刍品味之五:信号signal处理
查看>>
Set添加自定义方法对象如何保证唯一性
查看>>
站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma
查看>>
技术工坊|浅谈区块链的Layer2扩展(北京)
查看>>
SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
查看>>
Apache和PHP结合 及 Apache默认虚拟主机
查看>>
添加自定义监控项目配置邮件告警测试告警不发邮件的问题处理
查看>>
solidity智能合约的经典设计模式
查看>>
华为交换网络基础、基本配置、STP/RSTP
查看>>
SpringCloud 微服务 (十七) 容器部署 Docker
查看>>
不定项选择题
查看>>
netty 分析博客
查看>>
Spring Cloud构建微服务架构服务注册与发现
查看>>
BCGControlBar教程:如何将MFC控件的BCGControlBarBCGSuite添加到对话框中
查看>>
深入理解Java8 Lambda表达式
查看>>