使用JAXB时

没有多少示例可以说明这一点,但是如何在应用程序中使用JAXB可以在性能(和内存使用)方面产生巨大差异。

这个例子

在此博客文章中,我将使用一个名为Membership的示例对象,看起来像这样:

使用JAXB

我们将使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值