java重写post请求参数_记录spring-cloud-gateway获取post请
求。。。
介绍⼀下框架版本
spring-boot:2.2.1.RELEASE
spring-cloud:Hoxton.RELEASE(2.2.0.RELEASE)
spring-cloud-gateway:2.2.0.RELEASE
在⽹上了很多版本的代码,不起作⽤,要么获取不到body数据,要么重新封装request到后端服务后,报⽂丢失或者最⼤1024b数据,⽽且代码繁琐。
后⾯在博客园⾥⼀位⼤佬提供的解决⽅案
@Component
public class CacheBodyGlobalFilter implements Ordered, GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (Request().getHeaders().getContentType() == null) {
return chain.filter(exchange);
} else {
return DataBufferUtils.Request().getBody())
.flatMap(dataBuffer -> {
Flux cachedFlux = Flux
.defer(() -> Flux.just(dataBuffer.slice(0, adableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
@Override
public Flux getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest).build());
});
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
主要思路就是在优先级最⾼的过滤器⾥⾯,CacheBodyGlobalFilter这个全局过滤器的⽬的就是把原有的request请求中的body内容读出来,并且使⽤ServerHttpRequestDecorator这个请求装饰器对request进⾏包装,重写getBody⽅法,并把包装后的请求放到过滤器链中传递下去。这样后⾯的过滤器中再使⽤Request().getBody()来获取body时,实际上就是调⽤的重载后的getBody⽅法,获取的最先已经缓存了的body数据。这样就能够实现body的多次读取了。
过滤器优先级不⼀定是最⾼,但是要在要获取body之前执⾏,然后后⾯在⾝份鉴定的等过滤器⾥⾯,获取到body
@Component
@Slf4j
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
return -2;
}
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest serverHttpRequest = Request();
ServerHttpResponse originalResponse = Response();
//如果是post请求,将请求体取出来,再写⼊
HttpMethod method = Method();
//请求参数,post从请求⾥获取请求体
String requestBodyStr = HttpMethod.POST.equals(method) ? resolveBodyFromRequest(serverHttpRequest) : null;
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono writeWith(Publisher extends DataBuffer> body) {
if (body instanceof Flux) {
Flux extends DataBuffer> fluxBody = (Flux extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {//解决返回体分段传输
StringBuffer stringBuffer = new StringBuffer();
dataBuffers.forEach(dataBuffer -> {
byte[] content = new adableByteCount()];
try {
stringBuffer.append(new String(content, "utf-8"));
} catch (Exception e) {
<("--list.add--error", e);
}
});
String result = String();
//TODO,result就是response的值,想修改、查看就随意⽽为了
String url = Path().toString();
String urlParams = QueryParams().toSingleValueMap());
JSONObject jsonObject = JSONObject.parseObject(result);
log.info("请求长度:" + StringUtils.length(requestBodyStr) + ",返回data长度:" +
StringUtils.String("data")));
log.info("请求地址:【{}】请求参数:GET【{}】|POST:【\n{}\n】,响应数据:【\n{}\n】", url, urlParams, requestBodyStr, result); byte[] uppedContent = new Bytes(), 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());
}
/**
* 从Flux中获取字符串的⽅法
*
* @return 请求体
*/
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
/
/获取请求体
Flux body = Body();
AtomicReference bodyRef = new AtomicReference<>();
body.subscribe(buffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); lease(buffer);
bodyRef.String());
});
java重写和重载的区别//获取request body
();
}
}
这⾥可以把请求地址、参数、body、响应数据⼀起打印出来,测试的post请求
请求参数有56.97kb,后端order-center的接收打印,把整个数据完全接收并返回出去
⽹关的打印请求参数数据
再来⼀个get请求的
其他的put、delete等请求均试过正常请求
⽤postman的压测结果和对⽐,数据都完全正常,并且能通过json格式化,说明数据格式也保持了⼀致代码还有很多可以优化改进的地⽅,根据⾃⼰的也⽆需求来,⽐如签名、token等统⼀校验处理如您对本⽂有疑问或者有任何想说的,请点击进⾏留⾔回复,万千⽹友为您解惑!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论