Оглавление
Решение 1. Метод пошагового слушателя
Сценарий 2: Метка остановки StepExecution
введение
Продолжайте читать предыдущую статью: Методы запуска заданий Spring Batch . После понимания методов запуска заданий Spring Batch давайте узнаем о методах запуска заданий Spring Batch и методах остановки заданий. Вот три основных метода.
обзор
Возможны 3 ситуации остановки задания:
-
естественный конец
Задание успешно выполнено и нормально остановлено. В настоящее время состояние возврата задания: ЗАВЕРШЕНО.
-
Процесс выполнения нештатного завершения задания останавливается из-за различных неожиданных прерываний задания, и большинство заданий возвращают статус: FAILED.
-
конец программирования
Результат обработки данных на определенном шаге не соответствует предпосылкам для выполнения следующего шага. Остановить его вручную. Как правило, статус возврата устанавливается в: ОСТАНОВЛЕНО
Приведенные выше 1 и 2 случаи относительно просты, давайте сосредоточимся на третьем: остановить задание программно.
нуждаться
Моделирование рабочего сценария
1> Есть класс ресурсов, который имеет 2 атрибута: total: totalCount = 100, read count: readCount = 0
2> Шаги дизайна 2, шаг 1 используется для наложения readCount для имитации чтения ресурсов из базы данных, шаг 2 используется для выполнения логики
3> Когда totalCount == readCount, это нормальная ситуация и нормально заканчивается. Если нет, то это ненормальное состояние. В это время шаг 2 не выполняется, и задание останавливается напрямую.
4> Восстановите данные, начните выполнение с шага 1 и завершите работу.
public class ResouceCount {
public static int totalCount = 100; //总数
public static int readCount = 0; //读取数
}
Существует два способа достижения вышеуказанных требований.
Решение 1. Метод пошагового слушателя
слушатель
public class StopStepListener implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
//不满足
if(ResouceCount.totalCount != ResouceCount.readCount){
return ExitStatus.STOPPED; //手动停止,后续可以重启
}
return stepExecution.getExitStatus();
}
}
код
package com.langfeiyes.batch._16_job_stop;
import com.langfeiyes.batch._01_hello.HelloJob;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableBatchProcessing
public class ListenerJobStopJob {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
private int readCount = 50; //模拟只读取50个
@Bean
public Tasklet tasklet1(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
for (int i = 1; i <= readCount; i++) {
System.out.println("---------------step1执行-"+i+"------------------");
ResouceCount.readCount ++;
}
return RepeatStatus.FINISHED;
}
};
}
@Bean
public Tasklet tasklet2(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.err.println("step2执行了.......");
System.err.println("readCount:" + ResouceCount.readCount + ", totalCount:" + ResouceCount.totalCount);
return RepeatStatus.FINISHED;
}
};
}
@Bean
public StopStepListener stopStepListener(){
return new StopStepListener();
}
@Bean
public Step step1(){
return stepBuilderFactory.get("step1")
.tasklet(tasklet1())
.listener(stopStepListener())
.allowStartIfComplete(true) //执行完后,运行重启
.build();
}
@Bean
public Step step2(){
return stepBuilderFactory.get("step2")
.tasklet(tasklet2())
.build();
}
//定义作业
@Bean
public Job job(){
return jobBuilderFactory.get("job-stop-job")
.start(step1())
.on("STOPPED").stopAndRestart(step1())
.from(step1()).on("*").to(step2()).end()
.build();
}
public static void main(String[] args) {
SpringApplication.run(ListenerJobStopJob.class, args);
}
}
Первое выполнение: readCount в tasklet1 по умолчанию выполняется 50 раз, и условие не выполняется . )) разветвление, остановка и разрешение перезапуска - - При следующем перезапуске начните с шага 1
Второе выполнение, измените readCount = 100, запустите задание снова, задача 1 проходит 100 раз, удовлетворяет условиям, stopStepListener() afterStep нормально возвращается, и управление условием задания идет.from ( step1()).on("*") .to(step2()).end() ветвь, завершается нормально.
Примечание: В методе step1() необходимо добавить код .allowStartIfComplete(true), так как первое выполнение шага step1 не соответствует условиям, но все же относится к нормальному концу (процесс tasklet1 выполняется нормально ) , код состояния: COMPLETED, the first Для второго перезапуска шаг 1, который завершается нормально, по умолчанию не может быть выполнен, поэтому он должен быть установлен: .allowStartIfComplete(true) разрешает перезапуск шага 1, даже если он завершен.
Сценарий 2: Метка остановки StepExecution
package com.langfeiyes.batch._17_job_stop_sign;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableBatchProcessing
public class SignJobStopJob {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
private int readCount = 50; //模拟只读取50个
@Bean
public Tasklet tasklet1(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
for (int i = 1; i <= readCount; i++) {
System.out.println("---------------step1执行-"+i+"------------------");
ResouceCount.readCount ++;
}
if(ResouceCount.readCount != ResouceCount.totalCount){
chunkContext.getStepContext().getStepExecution().setTerminateOnly();
}
return RepeatStatus.FINISHED;
}
};
}
@Bean
public Tasklet tasklet2(){
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.err.println("step2执行了.......");
System.err.println("readCount:" + ResouceCount.readCount + ", totalCount:" + ResouceCount.totalCount);
return RepeatStatus.FINISHED;
}
};
}
@Bean
public Step step1(){
return stepBuilderFactory.get("step1")
.tasklet(tasklet1())
.allowStartIfComplete(true)
.build();
}
@Bean
public Step step2(){
return stepBuilderFactory.get("step2")
.tasklet(tasklet2())
.build();
}
//定义作业
@Bean
public Job job(){
return jobBuilderFactory.get("job-stop-job")
.start(step1())
//.on("STOPPED").stopAndRestart(step1())
//.from(step1()).on("*").to(step2()).end()
.next(step2())
.build();
}
public static void main(String[] args) {
SpringApplication.run(SignJobStopJob.class, args);
}
}
Есть 2 измененных кода
task1(), ниже есть еще решения
if(ResouceCount.readCount != ResouceCount.totalCount){
chunkContext.getStepContext().getStepExecution().setTerminateOnly();
}
Среди них StepExecution#setTerminateOnly() устанавливает отметку остановки для запущенного stepExecution, а Spring Batch сразу останавливает шаг после распознавания, а затем останавливает процесс.
работа () изменяется
return jobBuilderFactory.get("job-stop-job")
.start(step1())
.next(step2())
.build();
Последовательность стандартных шагов настройки.
На этом эта статья закончена. Если вы хотите знать, что будет дальше, пожалуйста, прослушайте следующую главу, чтобы разбить ее на части~
Перейти к видео версии
Если вас не устраивает чтение текста, вы можете переключиться на видеоверсию: