我对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个大请求,这种方法失败了 - 对于其中一个请求,我得到流关闭错误。
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,但我需要一个有效的解决方案,如果你能解释我做错了什么就会很棒。
如果你不能直接回答这个问题,请至少回答其中一些问题:
为什么需要此行 message.setContent(OutputStream.class,cwos); ? 我不想修改流内容,只是得到里面的内容,那么我为什么要阅读然后再发送内容呢?
可能有比这个 message.getContent(OutputStream.class); 更合适的格式(要获取的类)?
可能我应该使用另一个拦截阶段?
有一种方法 onClose ,在流关闭或AFTER之前触发?这什么时候发生的?我不希望在将内容作为请求发送给客户端之前关闭strem。
提前致谢!
答案 0 :(得分:3)
我理解你的问题的方式:
如果您只想记录SOAP请求响应信封,您甚至不应该使用StreamInterceptor。最好使用LoggingInterceptor。回答你的第一个问题 message.setContent(OutputStream.class,cwos);拦截传出的soap消息并更改其中的内容。
如果您想继续使用StreamInterceptor,最终会使用相同的方法来获取OutputStream的内容。另一种方法是使用LoggingInterceptor。 有关这方面的更多信息 How to log Apache CXF Soap Request and Soap Response using Log4j
您可以继续使用pre-stream。但如果目的只是阅读邮件内容,则可以使用pre_invoke。使用一个而不是另一个没有优势。 这里有一个链接,可以让您了解如何扩展一个简单的类来实现LoggingInterceptor。 http://cxf.apache.org/docs/interceptors.html
How to get incoming & outgoing soap xml in a simple way using Apache CXF?