没有多少示例可以说明这一点,但是如何在应用程序中使用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 );
翻译自: https://www.javacodegeeks.com/2019/05/using-jaxb.html