SpringCloud gateway 统一响应结果,修复服务提供方response Body 为空时可正常返回
spring cloud gateway 统一响应结果网上较多资料的处理方案是如下:(https://blog.csdn.net/tianyaleixiaowu/article/details/83618037)import org.reactivestreams.Publisher;import org.springframework.cloud.gateway.filter.Gatewa...
·
spring cloud gateway 统一响应结果
网上较多资料的处理方案是如下:(https://blog.csdn.net/tianyaleixiaowu/article/details/83618037)
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
/**
* @author wuweifeng wrote on 2018/10/31.
*/
@Component
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
// -1 is response write filter, must be called before that
return -2;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
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) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.map(dataBuffer -> {
// probably should reuse buffers
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
//释放掉内存
DataBufferUtils.release(dataBuffer);
String s = new String(content, Charset.forName("UTF-8"));
//TODO,s就是response的值,想修改、查看就随意而为了
byte[] uppedContent = new String(content, Charset.forName("UTF-8")).getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
// if body is not a flux. never got there.
return super.writeWith(body);
}
};
// replace response with decorator
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}
以上处理当服务提供方返回参数为空时,无法正常的构建统一的返回结果.如下:
@PutMapping(value="/user")
public void update(){
}
但是在前端处理时,只能收到响应200结果状态
在应用过程中前端都是对结果进行统一拦截处理,希望返回标准化的结果,如图(结果格式自行定义,小生使用的是CODE,MSG,DATA的格式)
有数据时
{
"data": {
"token": “”
},
"code": 0,
"message": "success"
}
无数据时
{
"code": 0,
"message": "success"
}
但是在资料中面对这种情况 是无法接达到预期结果,
官方提供了一个ModifyResponseBodyGatewayFilterFactory,可以简单快速的对response进行修改,但是也会遇到以上的问题
最后基于继承ServerHttpResponseDecorator 的方法进行了一些调整达到了目的。
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.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;
import java.util.Map;
/**
* Created by Zone
*/
public class CommonResponseDecorator extends ServerHttpResponseDecorator {
private DataBufferFactory bufferFactory ;
public CommonResponseDecorator(ServerHttpResponse delegate) {
super(delegate);
this.bufferFactory = delegate.bufferFactory();
}
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
if(this.getDelegate().getHeaders().getContentLength()<1){
ResponseVo response = new ResponseVo();
response.setCode(0);
response.setMessage("success");
byte[] resp = BeanMapper.toJsonString(response).getBytes(Charset.forName("UTF-8"));
this.getDelegate().getHeaders().setContentLength(resp.length);
return getDelegate().writeWith(Flux.just(bufferFactory.wrap(resp)));
}
return super.writeWith(fluxBody.map(dataBuffer -> {
// probably should reuse buffers
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
// 释放掉内存
DataBufferUtils.release(dataBuffer);
String rs = new String(content, Charset.forName("UTF-8"));
ResponseVo response = new ResponseVo();
response.setCode(0);
response.setMessage("success");
response.setData(BeanMapper.parseJson(rs,Map.class));
byte[] newRs = BeanMapper.toJsonString(response).getBytes(Charset.forName("UTF-8"));
this.getDelegate().getHeaders().setContentLength(newRs.length);//如果不重新设置长度则收不到消息。
return bufferFactory.wrap(newRs);
}));
}
return super.writeWith(body);
}
}
/**
* Created by Zone
*/
public class WrapperResponseFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
return -2;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
ServerHttpResponseDecorator decoratedResponse = new CommonResponseDecorator(originalResponse);
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}
本人对flux 机制不是特别了解,在识别响应结果是否为空时通过response的ContentLength长度进行识别
运行后结果如下
更多推荐
已为社区贡献1条内容
所有评论(0)