在将我的spring服务器从servlet迁移到reactive时,我不得不将代码中的所有过滤器都改为WebFilter,其中一个过滤器是解压缩压缩的内容,但我不能用新的WebFilter做同样的事情。使用servlet时,我用GzipInputStream Package 了输入流。使用springreactive的最佳实践是什么?
vohkndzv1#
解决方案:
@Component public class GzipFilter implements WebFilter { private static final Logger LOG = LoggerFactory.getLogger(GzipFilter.class); public static final String CONTENT_ENCODING = "content-encoding"; public static final String GZIP = "gzip"; public static final String UTF_8 = "UTF-8"; @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (!isGzip(request)) { return chain.filter(exchange); } else { ServerHttpRequest mutatedRequest = new ServerHttpRequestWrapper(request); ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build(); return chain.filter(mutatedExchange); } } private boolean isGzip(ServerHttpRequest serverHttpRequest) { String encoding = serverHttpRequest.getHeaders().getFirst(CONTENT_ENCODING); return encoding != null && encoding.contains(GZIP); } private static class ServerHttpRequestWrapper implements ServerHttpRequest { private ServerHttpRequest request; public ServerHttpRequestWrapper(ServerHttpRequest request) { this.request = request; } private static byte[] getDeflatedBytes(GZIPInputStream gzipInputStream) throws IOException { StringWriter writer = new StringWriter(); IOUtils.copy(gzipInputStream, writer, UTF_8); return writer.toString().getBytes(); } @Override public String getId() { return request.getId(); } @Override public RequestPath getPath() { return request.getPath(); } @Override public MultiValueMap<String, String> getQueryParams() { return request.getQueryParams(); } @Override public MultiValueMap<String, HttpCookie> getCookies() { return request.getCookies(); } @Override public String getMethodValue() { return request.getMethodValue(); } @Override public URI getURI() { return request.getURI(); } @Override public Flux<DataBuffer> getBody() { Mono<DataBuffer> mono = request.getBody() .map(dataBuffer -> dataBuffer.asInputStream(true)) .reduce(SequenceInputStream::new) .map(inputStream -> { try (GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) { byte[] targetArray = getDeflatedBytes(gzipInputStream); return new DefaultDataBufferFactory().wrap(targetArray); } catch (IOException e) { throw new IllegalGzipRequest(String.format("failed to decompress gzip content. Path: %s", request.getPath())); } }); return mono.flux(); } @Override public HttpHeaders getHeaders() { return request.getHeaders(); } } }
o0lyfsai2#
爱@Yuval的解决方案!我最初的想法是将Flux转换为本地文件,然后解压缩本地文件。但是在Spring Reactive中下载一个文件太有挑战性了。我在Google上搜索了很多,大多数都阻止了获取文件的方式,(eidogg. Spring WebClient: How to stream large byte[] to file?和How to correctly read Flux and convert it to a single inputStream,它们都不起作用...)这没有意义,在React流中调用block()时会抛出错误。@Yuval拯救了我的一天!对我来说效果很好!
2条答案
按热度按时间vohkndzv1#
解决方案:
o0lyfsai2#
爱@Yuval的解决方案!
我最初的想法是将Flux转换为本地文件,然后解压缩本地文件。
但是在Spring Reactive中下载一个文件太有挑战性了。我在Google上搜索了很多,大多数都阻止了获取文件的方式,(eidogg. Spring WebClient: How to stream large byte[] to file?和How to correctly read Flux and convert it to a single inputStream,它们都不起作用...)这没有意义,在React流中调用block()时会抛出错误。
@Yuval拯救了我的一天!对我来说效果很好!