没有多少示例可以说明这一点,但是如何在应用程序中使用JAXB可以在性能(和内存使用)方面产生巨大差异。
这个例子
在此博客文章中,我将使用一个名为Membership
的示例对象,看起来像这样:
我们将使用JAXB将对象与XML封送或从XML解封。
在静态块中创建上下文(或至少一次)
我通常看到的最大错误是在每个请求上都创建了JAXB上下文:
public String marshal(Membership membership){
StringWriter stringWriter = new StringWriter();
try {
JAXBContext context = JAXBContext.newInstance(Membership. class );
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(membership, stringWriter);
String xml = stringWriter.toString();
stringWriter.close();
return xml;
} catch (JAXBException | IOException ex) {
throw new RuntimeException(ex);
}
}
public Membership unmarshal(String xml) {
try {
JAXBContext context = JAXBContext.newInstance(Membership. class );
Unmarshaller u = context.createUnmarshaller();
return (Membership)u.unmarshal( new StringReader(xml));
} catch (JAXBException ex) {
throw new RuntimeException(ex);
}
}
(也可参见示例代码这里 )
这里的问题是创建上下文的JAXBContext.newInstance
方法。 上下文仅在对象结构更改时更改,并且仅在代码更改时发生,因此我们可以安全地只执行一次,因此将其更改为在静态块中创建,如下所示:
public String marshal(Membership memberships){
StringWriter stringWriter = new StringWriter();
try {
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(memberships, stringWriter);
String xml = stringWriter.toString();
stringWriter.close();
return xml;
} catch (JAXBException | IOException ex) {
throw new RuntimeException(ex);
}
}
public Membership unmarshal(String xml) {
try {
Unmarshaller u = context.createUnmarshaller();
return (Membership)u.unmarshal( new StringReader(xml));
} catch (JAXBException ex) {
throw new RuntimeException(ex);
}
}
private static JAXBContext context;
static {
try {
context = JAXBContext.newInstance(Membership. class );
} catch (JAXBException ex) {
throw new RuntimeException(ex);
}
}
(也可参见示例代码这里 )
因此,让我们看看有什么区别。
批处理示例。
如果我们在一个循环中(一次一个)将10000个对象与XML相互转换,则结果如下:
with Bad util Testing 10000 Marshal took: 10804 ms 13762 Unmarshal took: 13762 ms
然后加上静态块:
with Good util Testing 10000 Marshal took: 90 ms Unmarshal took: 428 ms
那就是编组速度120倍,解组速度快32倍!!
( 这里有完整的示例)
并发示例。
同样,对多个并发请求执行此操作时,您应该看到相同的结果。 因此,当我们将其部署到某个服务器上(在我的示例中是扎带 ),并将REST端点暴露给封送和封送时,我们可以使用诸如siege之类的东西来生成并发流量到服务器:
错误示例的输出:
Transactions: 255 hits Availability: 100.00 % Elapsed time: 7.91 secs Data transferred: 0.54 MB Response time: 5.13 secs Transaction rate: 32.24 trans/sec Throughput: 0.07 MB/sec Concurrency: 165.52 Successful transactions: 255 Failed transactions: 0 Longest transaction: 6.88 Shortest transaction: 3.47
好例子的输出:
Transactions: 255 hits Availability: 100.00 % Elapsed time: 1.80 secs Data transferred: 0.53 MB Response time: 0.52 secs Transaction rate: 141.67 trans/sec Throughput: 0.30 MB/sec Concurrency: 73.12 Successful transactions: 255 Failed transactions: 0 Longest transaction: 0.78 Shortest transaction: 0.05
注意“并发性”值的差异(并发性是平均同时连接数,该数字随着服务器性能下降而增加)
( 这里有完整的示例)
当文件很大时。
如果输入文件太大,则可能会收到java.lang.OutOfMemoryError
异常。
为了确保可以有效地处理大文件,可以确保在创建输入时正在使用SAX Parser:
public Membership unmarshalWithSAX(InputStream xml){
try {
InputSource inputSource = new InputSource(xml);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware( true );
spf.setValidating( true );
SAXParser saxParser = spf.newSAXParser();
saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
XMLReader xmlReader = saxParser.getXMLReader();
SAXSource source = new SAXSource(xmlReader, inputSource);
Unmarshaller u = context.createUnmarshaller();
return (Membership)u.unmarshal(source);
} catch (ParserConfigurationException | SAXException | JAXBException ex) {
throw new RuntimeException(ex);
}
}
private static final String JAXP_SCHEMA_LANGUAGE = " http://java.sun.com/xml/jaxp/properties/schemaLanguage " ;
private static final String W3C_XML_SCHEMA = " http://www.w3.org/2001/XMLSchema " ;
( 这里有完整的示例)
得到全部
您可以在一个简单的库中获得所有“好”的东西:
在您的代码中使用它
(参见https://github.com/phillip-kruger/jaxb-lib )
<dependency>
<groupId>com.github.phillip-kruger.jaxb-library</groupId>
<artifactId>jaxb-lib</artifactId>
<version> 1.0 . 0 </version>
</dependency>
元帅
JaxbUtil jaxbUtil = new JaxbUtil();
byte [] xml = jaxbUtil.marshal(myJAXBObject);
元帅
JaxbUtil jaxbUtil = new JaxbUtil();
MyJAXBObject myJAXBObject = jaxbUtil.unmarshal(MyJAXBObject. class ,xml);
获取JAXB对象的XSD
XsdUtil xsdUtil = new XsdUtil();
String xsd = xsdUtil.getXsd(MyJAXBObject. class );