4

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

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

4

1 回答 1

1

是的,这是可能的。我写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);
        }
    }

}

onClose您将在方法中获得消息的 XML 。请参阅此评论://requestBuilder - is your actuall XML of the message.

于 2013-08-14T12:34:46.397 回答