1. введение
Мы используем Spring Batch для создания заданий из нескольких шагов, которые считывают, преобразуют и записывают данные. Если шаги в задании имеют несколько путей, аналогично использованию оператора if в нашем коде, мы говорим, что поток задания является условным .
В этом уроке мы рассмотрим два способа создания весенних пакетных заданий с условным потоком.
2. Статус выхода и статус пакета
Когда мы указываем условный шаг с помощью пакетной структуры Spring, мы используем статус завершения шага или задания. Поэтому нам необходимо понять разницу между статусом пакета и Статусом выхода в наших шагах и заданиях:
- Статус партии является перечислением, представляющим статус шага/задания, и используется пакетной платформой внутри
- Возможные значения: ЗАБРОШЕНО, ЗАВЕРШЕНО, НЕ УДАЛОСЬ, НАЧАТО, НАЧАТО, ОСТАНОВЛЕНО, ОСТАНОВЛЕНО, НЕИЗВЕСТНО
- Статус Выхода является состоянием шага, когда выполнение завершено, и используется для условного определения потока
По умолчанию статус Выхода шага или задания совпадает с его статусом пакета . Мы также можем установить пользовательский Статус выхода для управления потоком.
3. Условный поток
Допустим, у нас есть устройство Интернета вещей, которое отправляет нам измерения. Наши измерения устройства представляют собой массивы целых чисел, и нам нужно отправлять уведомления, если какие-либо из наших измерений содержат положительные целые числа.
Другими словами, нам нужно отправить уведомление, когда мы обнаружим положительное измерение.
3.1. Состояние выхода
Важно отметить, что мы используем статус выхода шага для управления условным потоком .
Чтобы установить статус завершения шага, нам нужно использовать метод Step Execution объекта setExitStatus . Для этого нам нужно создать ItemProcessor , который расширяет ItemListenerSupport и получает StepExecution шага .
Мы используем это, чтобы установить статус выхода нашего шага в NOTIFY , когда мы находим положительное число. Когда мы определяем статус выхода на основе данных в пакетном задании, мы можем использовать ItemProcessor .
Давайте посмотрим на наш классификатор Number Info , чтобы увидеть три метода, которые нам нужны:
public class NumberInfoClassifier extends ItemListenerSupportimplements ItemProcessor { private StepExecution stepExecution; @BeforeStep public void beforeStep(StepExecution stepExecution) { this.stepExecution = stepExecution; this.stepExecution.setExitStatus(new ExitStatus(QUIET)); } @Override public Integer process(NumberInfo numberInfo) throws Exception { return Integer.valueOf(numberInfo.getNumber()); } @Override public void afterProcess(NumberInfo item, Integer result) { super.afterProcess(item, result); if (item.isPositive()) { stepExecution.setExitStatus(new ExitStatus(NOTIFY)); } } }
Примечание: мы используем Обработчик элементов для установки Статуса выхода в этом примере, но мы могли бы так же легко сделать это в нашем шаге ItemReader или ItemWriter .
Наконец, когда мы создаем нашу работу, мы сообщаем нашему JobBuilderFactory отправлять уведомления о любом шаге, который завершается со статусом NOTIFY :
jobBuilderFactory.get("Number generator - second dataset") .start(dataProviderStep) .on("NOTIFY").to(notificationStep) .end() .build();
Также обратите внимание, что когда у нас есть дополнительные условные ветви и несколько кодов выхода, мы можем добавить их в нашу работу с помощью методов from и on из JobBuilderFacotry :
jobBuilderFactory.get("Number generator - second dataset") .start(dataProviderStep) .on("NOTIFY").to(notificationStep) .from(step).on("LOG_ERROR").to(errorLoggingStep) .end() .build();
Теперь в любое время ваш Обработчик элементов видит положительное число, он направит нашу работу на выполнение шага уведомления , который просто печатает сообщение в System.out :
Second Dataset Processor 11 Second Dataset Processor -2 Second Dataset Processor -3 [Number generator - second dataset] contains interesting data!!
Если бы у нас был набор данных без положительного числа, мы бы не увидели ваш шаг уведомления сообщение:
Second Dataset Processor -1 Second Dataset Processor -2 Second Dataset Processor -3
3.2. Программное Ветвление С Помощью JobExecutionDecider
В качестве альтернативы мы можем использовать класс, реализующий JobExecutionDecider для определения потока заданий. Это особенно полезно , если у нас есть внешние факторы для определения потока выполнения .
Чтобы использовать этот метод, нам сначала нужно изменить наш Обработчик элементов для удаления интерфейса ItemListenerSupport и метода @BeforeStep :
public class NumberInfoClassifierWithDecider extends ItemListenerSupportimplements ItemProcessor { @Override public Integer process(NumberInfo numberInfo) throws Exception { return Integer.valueOf(numberInfo.getNumber()); } }
Затем мы создаем класс decider, который определяет статус уведомления нашего шага:
public class NumberInfoDecider implements JobExecutionDecider { private boolean shouldNotify() { return true; } @Override public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) { if (shouldNotify()) { return new FlowExecutionStatus(NOTIFY); } else { return new FlowExecutionStatus(QUIET); } } }
Затем мы настраиваем наше Задание для использования решающего элемента в потоке:
jobBuilderFactory.get("Number generator - third dataset") .start(dataProviderStep) .next(new NumberInfoDecider()).on("NOTIFY").to(notificationStep) .end() .build();
4. Заключение
В этом кратком руководстве мы рассмотрели два варианта реализации условных потоков с помощью Spring Batch. Во-первых, мы рассмотрели, как использовать Статус выхода для управления потоком нашей работы.
Затем мы взглянули на то, как мы можем программно управлять потоком, определяя наш собственный JobExecutionDecider .
Как всегда, полный исходный код статьи доступен на GitHub .