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