Service 在ExaultInterceptor for CXF Web服务处记录请求xml on错误

Service 在ExaultInterceptor for CXF Web服务处记录请求xml on错误,service,web,log4j,cxf,Service,Web,Log4j,Cxf,当我遇到诸如模式验证失败之类的错误时,是否可以检索请求XML并将其记录到OutFaultInterceptor的文件中 我曾尝试在网上搜索,但似乎找不到与此相关的内容。是的,这是可能的。我编写了CxfOutInterceptor,用于获取消息的XML。代码如下: import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.io.Cache

当我遇到诸如模式验证失败之类的错误时,是否可以检索请求XML并将其记录到OutFaultInterceptor的文件中


我曾尝试在网上搜索,但似乎找不到与此相关的内容。

是的,这是可能的。我编写了
CxfOutInterceptor
,用于获取消息的XML。代码如下:

import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CacheAndWriteOutputStream;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.io.CachedOutputStreamCallback;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CxfOutInterceptor extends AbstractPhaseInterceptor<Message> {

    private static final Logger LOGGER = LoggerFactory.getLogger(CxfInInterceptor.class);

    public CxfOutInterceptor() {
        super(Phase.PRE_STREAM);
    }

    public static final String SINGLE_KEY = CxfOutInterceptor.class.getName() + ".Processed";

    private static final int LIMIT = 10 * 1024 * 1024;

    @Override
    public void handleFault(Message message) {
        LOGGER.trace("handleFault");
        try {
            internalHandleMessage(message);
        } catch (Throwable ex) {
            LOGGER.error("Exception thrown by internalHandleMessage: ", ex);
        } finally {
            LOGGER.trace("handleFault - end");
        }
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        LOGGER.trace("handleMessage");
        try {
            if (onceOnly(message)) {
                LOGGER.debug("handled message previously");
                return;
            }
            internalHandleMessage(message);
        } finally {
            LOGGER.trace("handleMessage - end");
        }
    }

    private class LogCallback implements CachedOutputStreamCallback {

        private final Message message;

        private final OutputStream origStream;

        public LogCallback(final Message msg, final OutputStream os) {
            this.message = msg;
            this.origStream = os;
        }

        @Override
        public void onFlush(CachedOutputStream cos) {
        }

        @Override
        public void onClose(CachedOutputStream cos) {
            StringBuilder requestBuilder = new StringBuilder();
            String encoding = (String) message.get(Message.ENCODING);
            try {
                writePayload(requestBuilder, cos, encoding);
                //requestBuilder - is your actuall body of the message.
            } catch (IOException ex) {
                LOGGER.trace("Unable to write output stream to StringBuilder:\n" + ex.toString());
            }

            try {
                cos.lockOutputStream();
                cos.resetOut(null, false);
            } catch (Exception ex) {
                LOGGER.info("Ignoring exception");
            }
            message.setContent(OutputStream.class, origStream);
        }
    }

    private void internalHandleMessage(Message message) {
        final OutputStream os = message.getContent(OutputStream.class);
        final Writer writer = message.getContent(Writer.class);
        if (os == null && writer == null) {
            return;
        }

        if (os == null) {
            message.setContent(Writer.class, writer);
        } else {
            final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
            message.setContent(OutputStream.class, newOut);
            newOut.registerCallback(new LogCallback(message, os));
        }
    }

    private static boolean onceOnly(Message message) {
        if (message.getExchange().containsKey(SINGLE_KEY)) {
            return true;
        } else {
            message.getExchange().put(SINGLE_KEY, Boolean.TRUE);
            return false;
        }
    }

    private static void writePayload(StringBuilder builder, CachedOutputStream cos, String encoding)
            throws IOException {
        if (StringUtils.isEmpty(encoding)) {
            cos.writeCacheTo(builder, LIMIT);
        } else {
            cos.writeCacheTo(builder, encoding, LIMIT);
        }
    }

}
import org.apache.cxf.common.util.StringUtils;
导入org.apache.cxf.interceptor.Fault;
导入org.apache.cxf.io.cacheandWriteOutput流;
导入org.apache.cxf.io.CachedOutputStream;
导入org.apache.cxf.io.CachedOutStreamCallback;
导入org.apache.cxf.message.message;
导入org.apache.cxf.phase.AbstractPhaseInterceptor;
导入org.apache.cxf.phase.phase;
导入org.springframework.beans.factory.annotation.Autowired;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.Writer;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
公共类CxfOutInterceptor扩展了AbstractPhaseInterceptor{
私有静态最终记录器Logger=LoggerFactory.getLogger(CxfInInterceptor.class);
公共CXFOUTERCEPTOR(){
超级(相位预流);
}
public static final String SINGLE_KEY=CxfOutInterceptor.class.getName()+“.Processed”;
私有静态最终整数限制=10*1024*1024;
@凌驾
公共无效handleFault(消息消息){
LOGGER.trace(“handleFault”);
试一试{
internalHandleMessage(消息);
}捕获(可丢弃的ex){
错误(“internalHandleMessage引发的异常:”,ex);
}最后{
LOGGER.trace(“handleFault-end”);
}
}
@凌驾
public void handleMessage(消息消息消息)引发错误{
LOGGER.trace(“handleMessage”);
试一试{
如果(仅一次(消息)){
调试(“以前处理过的消息”);
返回;
}
internalHandleMessage(消息);
}最后{
trace(“handleMessage-end”);
}
}
私有类LogCallback实现CachedOutStreamCallback{
私人最终消息;
私有最终输出流origStream;
公共日志回调(最终消息消息,最终输出流os){
this.message=msg;
this.origStream=os;
}
@凌驾
公共void onFlush(CachedOutputStream cos){
}
@凌驾
公共void onClose(CachedOutputStream cos){
StringBuilder requestBuilder=新建StringBuilder();
字符串编码=(字符串)message.get(message.encoding);
试一试{
writePayload(请求生成器、cos、编码);
//requestBuilder-是消息的实际正文。
}捕获(IOEX异常){
trace(“无法将输出流写入StringBuilder:\n”+ex.toString());
}
试一试{
cos.lockOutputStream();
cos.resetOut(null,false);
}捕获(例外情况除外){
LOGGER.info(“忽略异常”);
}
message.setContent(OutputStream.class,origStream);
}
}
私有void internalHandleMessage(消息消息消息){
final OutputStream os=message.getContent(OutputStream.class);
final Writer=message.getContent(Writer.class);
if(os==null&&writer==null){
返回;
}
if(os==null){
message.setContent(Writer.class,Writer);
}否则{
final CacheAndWriteOutputStream newOut=新CacheAndWriteOutputStream(os);
message.setContent(OutputStream.class,newOut);
registerCallback(新的日志回调(消息,操作系统));
}
}
私有静态布尔onceOnly(消息){
if(message.getExchange().containsKey(单键)){
返回true;
}否则{
message.getExchange().put(单键,布尔值.TRUE);
返回false;
}
}
私有静态void writePayload(StringBuilder生成器、CachedOutput流cos、字符串编码)
抛出IOException{
if(StringUtils.isEmpty(编码)){
cos.writeCacheTo(建造商,限额);
}否则{
cos.writeCacheTo(生成器、编码、限制);
}
}
}

您将在
onClose
方法中获得消息的XML。请参阅此注释:
//requestBuilder-是消息的实际XML。

记录器中有轻微的输入错误。我肯定你的意思是
getLogger(CxfOutInterceptor.class)
而且,在某个时候,这必须向CXF注册类似于`ClientProxy.getClient(client.getoutfaultterceptors().add(new cxffaultoutineterceptor())`如果我将此拦截器添加为outFaultInterceptor,requestBuilder将包含响应的xml,而不是请求。