Немного примеров показывают это, но то, как вы используете JAXB в своем приложении, может сильно повлиять на производительность (и использование памяти).
Пример
В этом посте я буду использовать пример объекта с именем Membership который выглядит примерно так:

Мы будем маршалировать и демаршировать этот объект в и из XML с помощью JAXB.
Создать контекст в статическом блоке (или хотя бы один раз)
Самая большая ошибка, которую я обычно вижу, заключается в том, что контекст JAXB создается при каждом запросе:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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 который создает контекст. Контекст изменяется только в случае изменения структуры объекта, и это происходит только при изменении кода, поэтому мы можем безопасно сделать это только один раз, поэтому измените его, создав его в статическом блоке, например так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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 в цикле (по одному за раз), это будет результат:
|
1
2
3
4
|
Testing 10000 with Bad utilMarshal took: 10804 msUnmarshal took: 13762 ms |
а затем со статическим блоком:
|
1
2
3
4
|
Testing 10000 with Good utilMarshal took: 90 msUnmarshal took: 428 ms |
Это маршалинг в 120 раз, а маршаллинг в 32 раза быстрее!
(Полный пример здесь )
Пример параллелизма.
Точно так же при выполнении нескольких параллельных запросов вы должны увидеть одинаковые результаты. Поэтому, когда мы развернем это на каком-нибудь сервере (в моем примере это thorntail ) и выставим конечную точку REST маршалу и демаршалу, мы сможем использовать что-то вроде siege для генерации параллельного трафика на сервер:
Вывод плохого примера:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
Transactions: 255 hitsAvailability: 100.00 %Elapsed time: 7.91 secsData transferred: 0.54 MBResponse time: 5.13 secsTransaction rate: 32.24 trans/secThroughput: 0.07 MB/secConcurrency: 165.52Successful transactions: 255Failed transactions: 0Longest transaction: 6.88Shortest transaction: 3.47 |
Вывод хорошего примера:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
Transactions: 255 hitsAvailability: 100.00 %Elapsed time: 1.80 secsData transferred: 0.53 MBResponse time: 0.52 secsTransaction rate: 141.67 trans/secThroughput: 0.30 MB/secConcurrency: 73.12Successful transactions: 255Failed transactions: 0Longest transaction: 0.78Shortest transaction: 0.05 |
Обратите внимание на разницу значений «параллелизма» («Параллельность» — это среднее количество одновременных подключений, которое увеличивается с уменьшением производительности сервера).
(Полный пример здесь )
Когда файл очень очень большой.
Если ваш входной файл слишком большой, вы можете получить исключение java.lang.OutOfMemoryError .
Чтобы убедиться, что вы можете эффективно обрабатывать большие файлы, вы можете убедиться, что вы используете SAX Parser при создании ввода:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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"; |
(Полный пример здесь )
Получить все
Вы можете получить все «хорошее» в простой библиотеке:
Используя это в вашем коде
(См. Https://github.com/phillip-kruger/jaxb-lib )
|
1
2
3
4
5
|
<dependency> <groupId>com.github.phillip-kruger.jaxb-library</groupId> <artifactId>jaxb-lib</artifactId> <version>1.0.0</version> </dependency> |
маршал
|
1
2
|
JaxbUtil jaxbUtil = new JaxbUtil(); byte[] xml = jaxbUtil.marshal(myJAXBObject); |
распаковать
|
1
2
|
JaxbUtil jaxbUtil = new JaxbUtil(); MyJAXBObject myJAXBObject = jaxbUtil.unmarshal(MyJAXBObject.class,xml); |
Получение XSD для объекта JAXB
|
1
2
|
XsdUtil xsdUtil = new XsdUtil(); String xsd = xsdUtil.getXsd(MyJAXBObject.class); |
|
Опубликовано на Java Code Geeks с разрешения Филиппа Крюгера, партнера нашей программы JCG . Смотрите оригинальную статью здесь: При использовании JAXB… Мнения, высказанные участниками Java Code Geeks, являются их собственными. |