Java

В этой статье мы напишем свою реализацию интерфейсов ItemReader, ItemPocessor и ItemWriter, а так же сервис для управления всеми задачами в приложении. Написание собственных реализаций рассматриваемых интерфейсов может быть полезно для оптимизации и ускорения конкретной пакетной обработки.

Скачайте репозиторий и переключитесь на ветку step1:

Интерфейс ItemReader работает как итератор и используется как источник данных, которые необходимо обработать:

Источник данных ItemReader за одну итерацию должен возвращать один объект T, в нашем примере это один товар Product. Процесс итерирования продолжается до тех пор, пока метод read() не вернет null, тогда выполняется последняя обработка, последнее сохранение, и шаг заканчивается.

В последней версии Spring Batch 3.0.7 поставляются стандартные реализации ItemReader:

AggregateItemReader, AmqpItemReader, FlatFileItemReader, HibernateCursorItemReader, HibernatePagingItemReader, IbatisPagingItemReader, ItemReaderAdapter, JdbcCursorItemReader, JdbcPagingItemReader, JmsItemReader, JpaPagingItemReader, ListItemReader, MongoItemReader, Neo4jItemReader, RepositoryItemReader, StoredProcedureItemReader, StaxEventItemReader.

Для нашей задачи больше всего подходит FlatFileItemReader, но нам не нужна вся универсальность этой реализации и для увеличения производительности мы напишем свой узкопрофильный CsvItemReader:

Методы, аннотированные @BeforeStep, будут выполнены 1 раз перед запуском всего шага. Аналогично, метод destroy с аннотацией @AfterStep будет вызван после завершения шага вне зависимости от результата.

Для преобразования строки в объект мы используем не рефлексивный маппинг, а conversionService, который работает быстрее рефлексии. Для работы conversionService нужно заранее зарегистрировать в него конвертер строки в продукт StringProductConverter:

Теперь напишем реализацию интерфейса ItemProcessor:

В нашем примере название товара мы переводим в ВЕРХНИЙ РЕГИСТР:

И последнее, что нужно сделать – это реализовать интерфейс ItemWriter:

В последней версии Spring Batch 3.0.7 поставляются стандартные реализации ItemWriter:

AmqpItemWriter, CompositeItemWriter, FlatFileItemWriter, GemfireItemWriter, HibernateItemWriter, IbatisBatchItemWriter, ItemWriterAdapter, JdbcBatchItemWriter, JmsItemWriter, JpaItemWriter, MimeMessageItemWriter, MongoItemWriter, Neo4jItemWriter, PropertyExtractingDelegatingItemWriter, RepositoryItemWriter, StaxEventItemWriter.

Для записи в базу данных мы будем использовать JdbcTemplate:

Здесь формируется один запрос к базе данных на вставку всех элементов списка items. Items – это пачка (chunk) записей, полученная в результате многократного вызова ItemReader.read(). Размер items задается параметром chunk в StepBuilder (см. предыдущую часть). Особенностью данной реализации является отсутствие транзакции, что экономит немного ресурсов.

Теперь, модифицируем код из первой части руководства и заменим стандартные реализации ItemReader и ItemWriter на наши собственные, а так же заменим лямбда-выражение на SimpleProcessor. В результате получим код, который можно посмотреть в репозитории на шаге step1:

Теперь, когда всё готово, напишем небольшой сервис, который будет искать нашу задачу в реестре задач приложения и запускать ее на выполнение. Для начала определим интерфейс:

Реализация выглядит следующим образом:

Здесь используется стандартный бин JobRegistry, который знает обо всех задачах, определенных в проекте, и умеет возвращать экземпляр Job по названию задачи. Для использования бина JobRegistry необходимо в конфигурационный файл добавить следующие bean definitions:

В следующей части мы поговорим о передаче данных между шагами и о перезапуске пакетной задачи.

Spring Batch 3.0 – Часть 2: Кастомный ItemReader, ItemPocessor и ItemWriter