JAX-RS LoggingFilter记录请求实体后流被消耗无法发送如何解决
问题原因
你直接读取StreamDataBodyPart的streamEntity流后,原流的读取指针已经走到末尾,后续请求发送时自然无法再读取到数据。clientRequest.enableBuffering()仅作用于整个请求实体的序列化缓存,不会处理FormDataMultiPart内部单个BodyPart的流,所以之前的方案无效。
解决方法
参考你处理响应时的思路,对需要读取内容的BodyPart流先做缓存,读取完日志后给BodyPart重新赋值新的可重复读的流即可,修改后的核心逻辑如下:
@Override public void filter(ClientRequestContext requestContext) throws IOException { logger.trace(F_SEPARATOR); logger.trace(String.format(F_REQUEST, requestContext.getMethod(), requestContext.getUri())); requestContext.getHeaders() .keySet() .stream() .sorted() .forEach(key -> { logger.trace(String.format(F_HEADER, key, requestContext.getHeaders().get(key))); }); if (requestContext.hasEntity()) { if(requestContext.getHeaders().get("Content-Type").get(0).toString().equals("multipart/form-data")) { FormDataMultiPart formDataMultiPart = (FormDataMultiPart) requestContext.getEntity(); logger.trace(String.format(F_PART_NUMBER, formDataMultiPart.getBodyParts().size())); AtomicInteger index = new AtomicInteger(1); formDataMultiPart.getBodyParts().stream() .forEach(bodyPart -> { logger.trace(String.format(F_PART + F_PART_CONTENT_TYPE, index.get(), requestContext.getMediaType().toString())); if(bodyPart.getMediaType().toString().equals("text/xml")) { StreamDataBodyPart streamDataBodyPart = (StreamDataBodyPart) bodyPart; try { // 缓存流内容到字节数组 byte[] partBytes = IOUtils.toByteArray(streamDataBodyPart.getStreamEntity()); // 给bodyPart重新设置新的输入流,供后续请求发送使用 streamDataBodyPart.setStreamEntity(new ByteArrayInputStream(partBytes), StandardCharsets.UTF_8); // 从缓存的字节数组读取内容打日志 String part = new String(partBytes, StandardCharsets.UTF_8); logger.trace(String.format(F_PART + F_PART_CONTENT, index.get(), part)); } catch (IOException e) { logger.error("读取formData part内容失败", e); } } index.getAndIncrement(); }); } } requestContext.setProperty(PROPERTY_NANOS, System.nanoTime()); }
注意事项
- 上述代码依赖
org.apache.commons.io.IOUtils工具类实现流转字节数组,如果你项目没有引入该依赖,可以自行实现流到字节数组的转换逻辑 - 不同Jersey版本的
StreamDataBodyPart.setStreamEntity方法参数可能略有差异,可根据你使用的版本调整参数即可,核心逻辑都是替换内部的流实例 - 大体积的XML文件不建议打印日志,避免占用过多内存
内容的提问来源于stack exchange,提问作者tweetysat
相关产品推荐
相关产品推荐

