如何使用Apache CXF以简单的方式获取传入和传出的soap xml?

Mar*_*rco 15 logging soap cxf interceptor

我一直在摆弄CXF上的服务器端拦截器.但似乎实现简单的传入和传出拦截器并不是一项简单的任务,这些拦截器为我提供了包含SOAP XML的纯字符串.

我需要在拦截器中使用纯XML,以便我可以将它们用于特定的日志记录任务.标准的LogIn和LogOut拦截器不能胜任任务.是否有人愿意分享一些关于如何实现一个简单的传入拦截器的例子,它能够获取传入的SOAP XML和一个传出的拦截器来再次获取SOAP XML?

ann*_*rin 18

在这里找到传入拦截器的代码: 使用Apache CXF以XML格式记录请求/响应

我的传出拦截器:

import java.io.OutputStream;

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
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.Phase;

public class MyLogInterceptor extends LoggingOutInterceptor {

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

    @Override
    public void handleMessage(Message message) throws Fault {
        OutputStream out = message.getContent(OutputStream.class);
        final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(out);
        message.setContent(OutputStream.class, newOut);
        newOut.registerCallback(new LoggingCallback());
    }

    public class LoggingCallback implements CachedOutputStreamCallback {
        public void onFlush(CachedOutputStream cos) {
        }

        public void onClose(CachedOutputStream cos) {
            try {
                StringBuilder builder = new StringBuilder();
                cos.writeCacheTo(builder, limit);
                // here comes my xml:
                String soapXml = builder.toString();
            } catch (Exception e) {
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 刷新输出流并且其数据可供您检索后,将调用回调中的onClose()方法。 (2认同)

dul*_*lon 6

我无法让上述解决方案为我工作.这是我开发的,希望它可以帮助其他人:

我的"传入"拦截器:

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingMessage;

public class MyCxfSoapInInterceptor extends LoggingInInterceptor {


    public MyCxfSoapInInterceptor() {
        super();
    }

    @Override
    protected String formatLoggingMessage(LoggingMessage loggingMessage) {
        String soapXmlPayload = loggingMessage.getPayload() != null ? loggingMessage.getPayload().toString() : null;

        // do what you want with the payload... in my case, I stuck it in a JMS Queue

        return super.formatLoggingMessage(loggingMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的"外向"拦截器:

import org.apache.cxf.interceptor.LoggingMessage;
import org.apache.cxf.interceptor.LoggingOutInterceptor;

public class MyCxfSoapOutInterceptor extends LoggingOutInterceptor {

    public MyCxfSoapOutInterceptor() {
        super();
    }

    @Override
    protected String formatLoggingMessage(LoggingMessage loggingMessage) {
        String soapXmlPayload = loggingMessage.getPayload() != null ? loggingMessage.getPayload().toString() : null;

        // do what you want with the payload... in my case, I stuck it in a JMS Queue

        return super.formatLoggingMessage(loggingMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

我添加到spring框架应用程序上下文XML中的东西(记得在XML文件中定义两个拦截器)...

    ...

    <cxf:bus>
        <cxf:inInterceptors>
            <ref bean="myCxfSoapInInterceptor"/>
        </cxf:inInterceptors>
        <cxf:inFaultInterceptors>
            <ref bean="myCxfSoapInInterceptor"/>
        </cxf:inFaultInterceptors>
        <cxf:outInterceptors>
            <ref bean="myCxfSoapOutInterceptor"/>
        </cxf:outInterceptors>
        <cxf:outFaultInterceptors>
            <ref bean="myCxfSoapOutInterceptor"/>
        </cxf:outFaultInterceptors>
    </cxf:bus>

    ...
Run Code Online (Sandbox Code Playgroud)

注意,还有其他方法可以添加拦截器,例如通过注释,这将允许您只拦截特定的soap服务.上面添加拦截器的方法是"公共汽车"将拦截你所有的肥皂服务.


err*_*009 5

我只想再分享一个选项,如何同时将传入和传出消息组合在一起以进行某些日志记录,例如日志请求和对数据库的相应响应.

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Set;

public class CxfLoggingHandler implements SOAPHandler<SOAPMessageContext> {

private static final String SOAP_REQUEST_MSG_KEY = "REQ_MSG";

public Set<QName> getHeaders() {
    return Collections.EMPTY_SET;
}

public boolean handleMessage(SOAPMessageContext context) {
    Boolean outgoingMessage = (Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if (outgoingMessage) {
        // it is outgoing message. let's work
        SOAPPart request = (SOAPPart)context.get(SOAP_REQUEST_MSG_KEY);
        String requestString = convertDomToString(request);
        String responseString = convertDomToString(context.getMessage().getSOAPPart());
        String soapActionURI = ((QName)context.get(MessageContext.WSDL_OPERATION)).getLocalPart();
        // now you can output your request, response, and ws-operation    
    } else {
        // it is incoming message, saving it for future
        context.put(SOAP_REQUEST_MSG_KEY, context.getMessage().getSOAPPart());
    }
    return true;
}

public boolean handleFault(SOAPMessageContext context) {        
    return handleMessage(context);
}

private String convertDomToString(SOAPPart soap){
    final StringWriter sw = new StringWriter();
    try {
        TransformerFactory.newInstance().newTransformer().transform(
                new DOMSource(soap),
                new StreamResult(sw));
    } catch (TransformerException e) {
        // do something
    }
    return sw.toString();
}
}
Run Code Online (Sandbox Code Playgroud)

然后使用webservice连接该处理程序

<jaxws:endpoint id="wsEndpoint" implementor="#myWS" address="/myWS" >
    <jaxws:handlers>
        <bean class="com.package.handlers.CxfLoggingHandler"/>
    </jaxws:handlers>
</jaxws:endpoint>
Run Code Online (Sandbox Code Playgroud)