请看一段代码,这个是用来做代理的:
ServerHttpRequest frontEndReq = exchange.getRequest();
ServerHttpResponse frontEndResp = exchange.getResponse();
String path = frontEndReq.getPath().pathWithinApplication().value();
HttpMethod httpMethod = frontEndReq.getMethod();
RequestBodySpec reqBodySpec = webClient.method(httpMethod).
uri(backendServiceUrlPrefix.concat(path)).
headers(httpHeaders ->
{
httpHeaders.addAll(frontEndReq.getHeaders());
httpHeaders.remove("HOST");
});
RequestHeadersSpec<?> reqHeadersSpec;
if (requireHttpBody(httpMethod)) {
reqHeadersSpec = reqBodySpec.body(BodyInserters.fromDataBuffers(frontEndReq.getBody()));
} else {
reqHeadersSpec = reqBodySpec;
}
//调用后端服务
return reqHeadersSpec.exchange().timeout(Duration.ofMillis(backendServiceTimeoutInMillis)).
onErrorResume(ex ->
{
//调用后端服务异常(超时、网络问题)时,转发到后端异常-后控制器
//此处也可不用转发,用frontEndResp.writeWith(...)直接将异常响应写回给调用方
Map<String, Object> forwardAttrs = new HashMap<>();
forwardAttrs.put(Constant.BACKEND_EXCEPTION_ATTR_NAME, ex);
return WebfluxForwardingUtil.forward(Constant.BACKEND_EXCEPTION_PATH, exchange, forwardAttrs)
.then(Mono.empty());
}).flatMap(backendResponse ->
{
//将后端服务的响应回写到前端resp
frontEndResp.setStatusCode(backendResponse.statusCode());
frontEndResp.getHeaders().putAll(backendResponse.headers().asHttpHeaders());
return frontEndResp.writeWith(backendResponse.bodyToFlux(DataBuffer.class));
}
);
请留意最后一句:
return frontEndResp.writeWith(backendResponse.bodyToFlux(DataBuffer.class));
它的原理是,把目标服务器请求得到的响应转成DataBuffer,再把这个DataBuffer返回给客户端。我看了DataBuffer相关文章,都说这个类是把java nio的ByteBuffer与netty 的ByteBuf相结合操作的类。也就是说,这跟io里面的byte[] 是差不多的,都是把数据先写到内存里面。但万一这个是大文件上传或下载,不是消耗过多内存了吗?
我们下载文件,传统的httpServlectRequest是拿到它的Outputstream以流的方式写回,webflux对应应该怎么做?