CXF:记录请求和响应

时间:2013-12-24 13:47:02

标签: java xml soap cxf marshalling

我有一个soap web服务,我想将响应和请求记录为xml字符串。 我知道拦截器,但由于某种原因,这无所谓,我不能使用它们。 如何从xml消息被解组到的对象构造xml请求(和响应)?如何将对象重新编组为xml字符串?

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

为了Marshal / Unmarshall,您需要创建一个与XML文档相同的类“层次结构”。所以,例如:

<tests>
    <lib-data> 
         <library>Library</library> 
         <count>64018</count> 
         <test-data> 
            <title>Book title1</title> 
            <book>Book Name1</book> 
            <count>5</count> 
         </test-data> 
         <test-data> 
            <title>Book title2</title> 
            <book>Book Name3</book> 
            <count>5</count> 
         </test-data> 
         <test-data> 
            <title>Book title3</title> 
            <book>Book Name3</book> 
            <count>4</count> 
         </test-data> 
    </lib-data>
</tests>

我会创建一个带有单个属性的'tests'类 - 一个'lib-data'类的ArrayList。

在每个lib-data类中,我将创建一个名为library的String字段,一个名为count的int字段和一个'test-data'类的ArrayList。

对于每个测试数据类,我将创建String title和book属性以及int count属性。

从那里,只需添加正确的@XmlRootElement(在每个类之前)和@XmlElement(在每个属性之前)注释。在那之后,您可以使用Jaxb进行实际的编组和解组。

修改

对不起,你的问题非常开放,所以我不确定你创造了多少。

XML注释非常简单,对于'tests'类来说看起来像这样:

@XmlRootElement
public class Tests {

    @XmlElement(name="lib-data")
    ArrayList<LibData> libData;

    public Tests()
    {
        this.libData = new ArrayList<LibData>()
    }


    public ArrayList<LibData> getLibData() {
        return this.libData;
    }

    public void setLibData(ArrayList<LibData> libData) {
        this.libData = libData;
    }
}

我还会创建一个'MarshalHandler'类,它隐藏了编组和解组的实现细节:

public class MarshalHandler {

    private JAXBContext jc;
    private Unmarshaller unmarshaller;
    private Marshaller marshaler;

    public MarshalHandler(){
        jc = JAXBContext.newInstance(Tests.class);
        unmarshaller = jc.createUnmarshaller();
        marshaler = jc.createMarshaller();
    }


    public Test unmarshall(File f){
        return (Tests) unmarshaller.unmarshal(f);
    }

    public void marshal(Tests t, String fileLoc){
        OutputStream os = new FileOutputStream(fileLoc);
        marshaler.marshal(t, os);
        os.flush();
        os.close();
    }
}

(我没有编译或测试过该代码。它可能包含一两个错误,绝对不会考虑异常)

现在,您如何处理MarshalHandler的细节完全取决于您,并将受到您的程序整体设计的影响。例如,您可能希望您的marshal方法返回StreamResult而不是保存到预定的fileLoc。也许你正在抓取这个SOAP响应并将其保存为字节数组,在这种情况下,能够将该数组直接传递给unmarshall方法会很不错。但是,如果没有更多细节,很难说。

答案 1 :(得分:2)

你知道使用拦截器是到目前为止最简单的方法吗?记录拦截器就是这样做的。

那就是说,如果你不能轻易做事,那么你必须尝试别的东西。例如,您可以拥有自己的JAXBContext并使用它来写出值以用于记录目的; 完全不会相同,但它会非常接近。

// I assume you've already JAXB-annotated these classes anyway.
JAXBContext c = JAXBContext.newInstance(YourInputPOJO.class, YourOutputPOJO.class);

public YourOutputPOJO theMethod(YourInputPOJO input) {
    logMessage("in", "theMethod", input);
    YourOutputPOJO output = ...;
    logMessage("out", "theMethod", output);
    return output;
}

private void logMessage(String dir, String method, Object message) {
    Marshaller m = c.createMarshaller();
    Writer out = new StringWriter();
    m.marshal(message, out);
    log.info("message " + dir + ":" + method + "(" + out + ")");
}

不要在每次通话时都使用JAXBContext - 它非常昂贵 - 但是Marshaller也不算太差。不要在线程之间共享Marshaller,但在创建之后JAXBContext是线程安全的。而且我完全省略了异常处理......

答案 2 :(得分:0)

CXF内置了日志记录功能,它只需要一个xml条目

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:cxf="http://cxf.apache.org/core"
      xsi:schemaLocation="
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus> 
</beans>

参考:http://cxf.apache.org/docs/configuration.html