我在 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,但我需要一个可行的解决方案,如果你能解释我做错了什么,那就太好了。
如果您不能直接回答这个问题,请至少回答以下一些问题:
为什么需要这一行 message.setContent(OutputStream.class, cwos);? 我不想修改流内容,只是获取里面的内容,为什么还要读取内容再发送呢?
可能有比这个 message.getContent(OutputStream.class); 更合适的格式(要获取的类)?
也许我应该使用另一个拦截器阶段?
有一个方法onClose,它在流关闭之前或之后触发?什么时候发生?我不希望在将内容作为请求发送给客户端之前关闭 strem。
提前致谢!
最佳答案
我理解你的问题的方式:
如果您只想记录 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_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/