Я делаю запрос на определенный сервис который отдаем мне очень медленно большой xml
Мне нужно не дожидаясь полного ответа документа начать читать и преобразовывать некоторые элементы xml в java-объекты через Jaxb и производить с ними не который операции
Как такое реализовать с помощью reactive spring и возможно ли?
Ответ
Попытался сделать максимально простой пример. Использовал java 9.
Исходные данные:
Xml вида:
Класс в который будет маппится содержимое тега person
@XmlAccessorType(XmlAccessType.FIELD)
private static class Person {
@XmlElement
private String name;
@XmlElement
private String surname;
@Override
public String toString() {
return String.format("Person{name=%s, surname=%s}", name, surname);
}
}
Теперь нам необходимо написать publisher который будет производить анмаршаллинг:
private static class MyPublisher extends SubmissionPublisher
void run(String fileName) {
try {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
int count = Integer.parseInt(xsr.getAttributeValue(null, "count"));
for (int i = 0; i < count; i++) {
xsr.nextTag();
JAXBContext jc = JAXBContext.newInstance(Person.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement
Ничего сложного - читаем первый тег, из него получаем значением атрибута count. Далее в цикле читаем последующие теги, преобразуем в объекты класса Person и отправляем подписчиками
Subscriber может выглядить следующим образом:
public static class PrintSubscriber implements Flow.Subscriber
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
}
@Override
public void onNext(Person item) {
System.out.println("Received item: " + item);
subscription.request(1);
}
@Override
public void onError(Throwable error) {
System.out.println("Error occurred: " + error.getMessage());
}
@Override
public void onComplete() {
System.out.println("PrintSubscriber is complete");
}
}
Как заставить все это работать вместе? Очень просто - создаем сначала publisher, потом subscriber Одного подписываем на другово и запускаем метод run для разбора xml
MyPublisher publisher = new MyPublisher();
publisher.subscribe(new PrintSubscriber());
publisher.run("demo.xml");
TimeUnit.MINUTES.sleep(1);
publisher.close();
Запуск
Как известно в java 9 ввели модули, работа с xml отсутствует в дефолтном модуле java.base, поэтому в настройках своего модуля потребуется прописать зависимости. Выглядит это примерно так module-info.java :
open module ru.izebit {
requires java.xml;
requires java.xml.bind;
}
PS java.xml.bind - deprecated, но до java 10 пользоваться еще можно, потом удалят ☹️
Комментариев нет:
Отправить комментарий