You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache CXF拦截器如何获取完整响应体?解决大内容截断问题

问题分析

你遇到的问题根源在于拦截器的执行阶段PRE_PROTOCOL_ENDING过早,此时响应内容还未完全写入CachedOutputStream,因此只能读取到部分数据。

解决方案

方案1:调整拦截器执行阶段

将拦截器的阶段改为Phase.POST_STREAM,这个阶段是在响应流完全处理完成后触发,能确保获取完整的响应内容。

修改构造方法:

public LogResponseInterceptor(MinioService minioService, AdministrationWebClient administrationWebClient) {
    super(Phase.POST_STREAM); // 替换为POST_STREAM阶段
    this.minioService = minioService;
    this.administrationWebClient = administrationWebClient;
}

方案2:强制缓存完整响应流(适配原阶段)

如果必须保留原阶段,需要手动替换消息的输出流为缓存流,确保所有响应内容被缓存后再读取:

@Override
public void handleMessage(Message message) throws Fault {
    try {
        OutputStream originalOutputStream = message.getContent(OutputStream.class);
        CachedOutputStream cachedOutputStream = new CachedOutputStream();
        
        // 替换原始输出流,让所有响应内容写入缓存
        message.setContent(OutputStream.class, cachedOutputStream);
        
        // 继续执行拦截链,完成响应内容的写入
        message.getInterceptorChain().doIntercept(message);
        
        // 确保缓存流内容完全写入并获取完整输入流
        cachedOutputStream.flush();
        cachedOutputStream.close();
        try (InputStream inputStream = cachedOutputStream.getInputStream()) {
            UUID uuid = UUID.randomUUID();
            minioService.uploadFile(
                    inputStream, Constantas.MinioConst.MINIO_SPV_OUT_PATH, uuid.toString(), "application/xml"
            );

            // 后续业务逻辑处理
            SpvRecord spvRecord = SpvRequestContext.getSpvRequest();
            spvRecord.setRequestState(RequestState.COMPLETED);
            spvRecord.setResponseXmlUrl(Constantas.MinioConst.MINIO_SPV_OUT_PATH + uuid);
            spvRecord.setFinishDate(ZonedDateTime.now());
            log.info("End spv action with {}", spvRecord);

            spvRecord.setRequestNumber(administrationWebClient.getSpvLastRequestNumber() + 1);
            administrationWebClient.createSpvRecord(spvRecord);
        }
        
        // 将缓存内容写回原始输出流,确保客户端能收到完整响应
        cachedOutputStream.writeCacheTo(originalOutputStream);
        message.setContent(OutputStream.class, originalOutputStream);

    } catch (IOException e) {
        log.error("### Error while get response xml");
        throw new RuntimeException(e);
    } finally {
        SpvRequestContext.clear();
    }
}
补充提示
  • 若使用CachedOutputStream,可通过cachedOutputStream.setThreshold(int)调整缓存阈值,避免因默认缓存大小不足导致内容截断。
  • 方案1是更简洁的官方推荐方式,优先使用。

内容的提问来源于stack exchange,提问作者Gimaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:50:37