java - 在 CXF 拦截器中保存出站消息

标签 java io cxf

我在 CXF 方面遇到了一个非常棘手的问题,我试图解决(未成功)一个多月。我读过很多类似的问题,但没有任何帮助。

首先介绍一下我用来保存出站消息的部分代码:

  public void handleMessage(SoapMessage message) throws Fault {
        OutputStream os = message.getContent(OutputStream.class);
        CacheAndWriteOutputStream cwos = new CacheAndWriteOutputStream(os);
        message.setContent(OutputStream.class, cwos);
        cwos.registerCallback(new LoggingOutCallBack());
    }

    class LoggingOutCallBack implements CachedOutputStreamCallback
    {
        public void onClose (CachedOutputStream cos)
        {
            try
            {
                String result = IOUtils.toString(cos.getInputStream());
            }
            catch (Exception e)
            {
                LogFactory.getLog(SwcFinalResponseInterceptor.class).error(ExceptionUtils.getStackTrace(e));
            }
        }

        public void onFlush (CachedOutputStream arg)
        {
        }
    }

我使用 PRE_STREAM 阶段。很多地方都提到了这种方法(例如 here ),但它会导致一些罕见的错误。我每天大约有 20000 个请求,所以,比如说,对于 200 个大请求,这种方法失败了 - 对于其中一个进一步的请求,我得到了 Stream closed 错误。

2013-12-19 15:37:47,902 [WARN ] org.apache.cxf.common.logging.LogUtils.doLog(LogUtils.java:400)
5880162-Interceptor for {http://service.ws.swc.comtech/}FrequentFlyerServiceWsService has thrown exception, unwinding now
5880163-org.apache.cxf.interceptor.Fault: Stream closed
5880164-        at org.apache.cxf.interceptor.LoggingInInterceptor.logging(LoggingInInterceptor.java:144)
5880165-        at org.apache.cxf.interceptor.LoggingInInterceptor.handleMessage(LoggingInInterceptor.java:73)

我绝对确定这是因为我代码中的这一行:

cos.getInputStream()

我已经在没有这一行的情况下测试了很多次,并且一切正常,但是当我添加这一行时,错误立即出现。 我想那是因为 CXF 不是在内存中而是在一些临时文件中存储大流的流数据。据描述here .

有趣的一点是,当我尝试自己加载测试服务器时,使用 curl 发送数千个繁重的请求,没有任何错误,但是当有很多客户端时,问题几乎立即开始出现。

我还找到了another solution而且,乍一看,它似乎工作正常,我没有更多
流关闭错误,但服务器开始跳过一些响应。

请帮帮我,我真的不知道我还能读什么或做什么,我不擅长流和 CXF,但我需要一个可行的解决方案,如果你能解释我做错了什么,那就太好了。

如果您不能直接回答这个问题,请至少回答以下一些问题:

  1. 为什么需要这一行 message.setContent(OutputStream.class, cwos);? 我不想修改流内容,只是获取里面的内容,为什么还要读取内容再发送呢?

  2. 可能有比这个 message.getContent(OutputStream.class); 更合适的格式(要获取的类)?

  3. 也许我应该使用另一个拦截器阶段?

  4. 有一个方法onClose,它在流关闭之前或之后触发?什么时候发生?我不希望在将内容作为请求发送给客户端之前关闭 strem。

提前致谢!

最佳答案

我理解你的问题的方式:

  1. 如果您只想记录 SOAP 请求响应信封,您甚至不应该使用 StreamInterceptor。最好使用 LoggingInterceptor。回答你的第一个问题 message.setContent(OutputStream.class, cwos);拦截传出的 soap 消息并更改其中的内容。

  2. 如果您想继续使用 StreamInterceptor,您最终会使用相同的方法来获取 OutputStream 的内容。另一种方法是使用 LoggingInterceptor。 有关此的更多信息 How to log Apache CXF Soap Request and Soap Response using Log4j

  3. 您可以继续使用预流。但如果目的只是阅读消息内容,则可以使用 pre_invoke。使用一个比另一个没有优势。 这是一个链接,可以让您了解如何扩展一个简单的类来实现 LoggingInterceptor。 http://cxf.apache.org/docs/interceptors.html

    How to get incoming & outgoing soap xml in a simple way using Apache CXF?

关于java - 在 CXF 拦截器中保存出站消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20685501/

相关文章:

ruby - 重新打开文件对象上的流

java - 元素 "http"的前缀 "http:conduit"未绑定(bind) - 这是什么意思?

java - 使用 CXF 运行 OpenCMIS 客户端

java - 具有自定义响应的 CXF 自定义验证拦截器不起作用

sockets - 套接字操作是否在系统级并行执行?

java - 从 C 客户端到 Java 服务器的 Http Post 字符串给出错误 400 Bad Request

java - 在文本字段中使用字母的方法

java - 有没有办法从Flash访问Java库?

每次循环后 Python 保存到磁盘的速度变慢

java - MySQL : Define Non Key as Unique per Compound Key