由于requestBody中的数据默认只能读取一次,如果在filter中读取后,那controller层就拿不到参数了,创建一个预处理Filter,把exchange和request都复制出来,把参数啥的放进去然后传递复制出来的exchange和request,后面执行的filter取的都是复制出来的request中的数据,controller层接收参数就不会有问题了。预处理Filter代码如下:
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* 最先执行的filter
* 后面的filter可以取到requestBody数据,也不会影响controller层数据的接收
*/
@Order(Integer.MIN_VALUE)
@Component
public class PreHandleFilter implements GlobalFilter {
public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (().getHeaders().getContentType() == null) {
return (exchange);
} else {
return (().getBody()).flatMap(dataBuffer -> {
(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux
.defer(() -> ((0, ())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);
return (().request(mutatedRequest).build());
});
}
}
}
后面的Filter中取requestBody用下面的方法:
/**
* 从requestBody中取出json或者form-data数据
*/
private String getRequestBodyFormRequest(ServerHttpRequest request) {
Flux<DataBuffer> body = ();
StringBuilder sb = new StringBuilder();
(buffer -> {
byte[] bytes = new byte[()];
(bytes);
String bodyString = new String(bytes, StandardCharsets.UTF_8);
(bodyString);
});
return ();
}
取出来的json格式数据是正常的,直接解析用就可以。
但是form-data数据是浏览器发起请求的所有数据,示例如下:
----------------------------656104841052683944615106
Content-Disposition: form-data; name="name"
----------------------------656104841052683944615106
Content-Disposition: form-data; name="addr"
jinan
----------------------------656104841052683944615106--
所以,需要解析上面的参数名和参数值。方法也写好了,直接拿去用吧:
/**
* 解析从requestBody中获取的form-data数据,转换为json格式
*/
private String handleFormData(String str, ServerHttpRequest request) {
String contentType = ().getContentType().toString();
String sep = "--" + ("multipart/form-data;boundary=", "");
String[] strs = ("\r\n");
boolean bankRow = false;// 空行
boolean keyRow = true;// name=xxx行
boolean append = false;// 内容是否拼接换行符
Map<String, String> params = new LinkedHashMap<>();// 这里保证接收顺序,所以用linkedhashmap
String s = null, key = null;
StringBuffer sb = new StringBuffer();
for (int i = 1, len = - 1; i < len; i++) {
s = strs[i];
if (keyRow) {
key = ("Content-Disposition: form-data; name=", "");
key = (1, () - 1);
keyRow = false;
bankRow = true;
sb = new StringBuffer();
append = false;
continue;
}
if ((s)) {
keyRow = true;
if (null != key) {
(key, ());
}
append = false;
continue;
}
if (bankRow) {
bankRow = false;
append = false;
continue;
}
if (append) {
("\r\n");
}
(s);
append = true;
}
if (null != key) {
(key, ());
}
return (params);// 这里是alibaba的fastjson,需要引入依赖
}
上面方法得出的数据示例为:{"name":"","addr":"jinan"}
-----------------完!