Spring-Cloud-Gateway获取multipart/form-data时无法正常获取
·
我们公司最近在升级springCloud2.X,由于Spring-Cloud-Gateway为官方推荐使用,所以最近在研究Spring-Cloud-Gateway,但是在实际开发过程中遇到了种种问题,其中耗时最长的为获取multipart/form-data里面的json字符串,在网上尝试了各种解决方案都无法成功获取,最终在GitHub的issue找到了一个大佬将此问题解决,废话不多说,直接上代码:
package com.XXX.center.gateway.filter;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.server.ServerWebExchange;
import com.XX.center.gateway.entity.GatewayContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* 获取请求内容.
* 此版本为是优化后的,在之前的版本中读取文件速度会变得很慢,导致响应时间过长。
*
* @author zyb
*/
@Component
public class GatewayContextFilter extends BaseFilter {
/**
* default HttpMessageReader.
*/
private static final List<HttpMessageReader<?>> MESSAGE_READERS = HandlerStrategies.withDefaults().messageReaders();
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
final ServerHttpRequest request = exchange.getRequest();
final String path = request.getPath().pathWithinApplication().value();
// GatewayContext中目前只有一个String的path和String的requestBody,如果需要别的参数在GatewayContext中追加即可,因为这只是一个实体类,所以就不放源码了,各位需要什么就往里面放什么即可
final GatewayContext gatewayContext = new GatewayContext();
gatewayContext.setPath(path);
// GatewayContext.CACHE_GATEWAY_CONTEXT是一个常量定义,至于常量的值是什么,只要保证key值唯一即可,各位随便定义
// 此处的作用为将我们需要的值放入Attributes中,以便在别的filter中使用,如果需要在别的地方使用,只需要exchange.getAttributes.get(GatewayContext.CACHE_GATEWAY_CONTEXT)即可
exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext);
return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
DataBufferUtils.retain(dataBuffer);
final Flux<DataBuffer> cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
final ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
final ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
return cacheBody(mutatedExchange, chain, gatewayContext);
});
}
@SuppressWarnings("unchecked")
private Mono<Void> cacheBody(ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext) {
final HttpHeaders headers = exchange.getRequest().getHeaders();
if (headers.getContentLength() == 0) {
return chain.filter(exchange);
}
final ResolvableType resolvableType;
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(headers.getContentType())) {
resolvableType = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class);
} else {
resolvableType = ResolvableType.forClass(String.class);
}
return MESSAGE_READERS.stream().filter(reader -> reader.canRead(resolvableType, exchange.getRequest().getHeaders().getContentType())).findFirst()
.orElseThrow(() -> new IllegalStateException("no suitable HttpMessageReader.")).readMono(resolvableType, exchange.getRequest(), Collections.emptyMap()).flatMap(resolvedBody -> {
if (resolvedBody instanceof MultiValueMap) {
final Part partInfo = (Part) ((MultiValueMap) resolvedBody).getFirst("info");
if (partInfo instanceof FormFieldPart) {
gatewayContext.setRequestBody(((FormFieldPart) partInfo).value());
}
} else {
gatewayContext.setRequestBody((String) resolvedBody);
}
return chain.filter(exchange);
});
}
}
望能帮助到大家
更多推荐
已为社区贡献1条内容
所有评论(0)