Рубрики
Без рубрики

Весенняя загрузка с весенним пакетом

Узнайте, как создать простую работу Spring Batch с помощью Spring Boot.

Автор оригинала: Jonathan Cook.

1. Обзор

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

В этом учебнике мы будем опираться на предыдущий и узнать, как настроить и создать базовое пакет-управляемое приложение с помощью Spring Boot.

2. Мейвен зависимостей

Во-первых, давайте добавим весна-загрузка-стартер-пакет к нашему пом.xml :


    org.springframework.boot
    spring-boot-starter-batch
    2.4.0

Мы также добавим org.hsqldb зависимости, которая доступна из Мавен Центральный тоже:


    org.hsqldb
    hsqldb
    2.5.1
    runtime

3. Определение простой весенней работы пакета

Мы собираемся создать работу, которая импортирует список кофе из файла CSV, преобразует его с помощью пользовательского процессора и хранит окончательные результаты в базе данных памяти .

3.1. Начало работы

Начнем с определения точки входа в нашу заявку:

@SpringBootApplication
public class SpringBootBatchProcessingApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootBatchProcessingApplication.class, args);
    }
}

Как мы видим, это стандартное приложение Spring Boot. Поскольку мы хотим использовать значения конфигурации по умолчанию, где это возможно, мы собираемся использовать очень легкий набор свойств конфигурации приложения.

Мы определим эти свойства в нашем src/main/resources/application.properts файл:

file.input=coffee-list.csv

Это свойство содержит расположение нашего входного списка кофе. Каждая линия содержит бренд, происхождение и некоторые характеристики нашего кофе:

Blue Mountain,Jamaica,Fruity
Lavazza,Colombia,Strong
Folgers,America,Smokey

Как мы увидим, это плоский файл CSV, что означает, что Spring может справиться с ним без какой-либо специальной настройки.

Далее мы добавим скрипт S’L схема-все.sql создать нашу кофейные таблица для хранения данных:

DROP TABLE coffee IF EXISTS;

CREATE TABLE coffee  (
    coffee_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
    brand VARCHAR(20),
    origin VARCHAR(20),
    characteristics VARCHAR(30)
);

Удобно Spring Boot запустит этот скрипт автоматически во время запуска .

3.2. Класс домена кофе

Впоследствии нам понадобится простой класс домена, чтобы держать наши кофейные изделия:

public class Coffee {

    private String brand;
    private String origin;
    private String characteristics;

    public Coffee(String brand, String origin, String characteristics) {
        this.brand = brand;
        this.origin = origin;
        this.characteristics = characteristics;
    }

    // getters and setters
}

Как уже упоминалось ранее, наши Кофейный объект содержит три свойства:

  • Бренд
  • Происхождение
  • Некоторые дополнительные характеристики

4. Конфигурация работы

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

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    
    @Value("${file.input}")
    private String fileInput;
    
    // ...
}

Во-первых, мы начинаем со стандартного весеннего @Configuration класс. Далее мы добавим @EnableBatchProcessing аннотация к нашему классу. Примечательно, что это дает нам доступ ко многим полезным бобов, которые поддерживают рабочие места и сэкономит нам много ног работы.

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

Для последней части нашей первоначальной конфигурации мы включаем ссылку на file.input собственности мы объявили ранее.

4.1. Читатель и писатель для нашей работы

Теперь мы можем пойти дальше и определить считыватель фасоли в нашей конфигурации:

@Bean
public FlatFileItemReader reader() {
    return new FlatFileItemReaderBuilder().name("coffeeItemReader")
      .resource(new ClassPathResource(fileInput))
      .delimited()
      .names(new String[] { "brand", "origin", "characteristics" })
      .fieldSetMapper(new BeanWrapperFieldSetMapper() {{
          setTargetType(Coffee.class);
      }})
      .build();
}

Короче говоря, наш читатель фасоли определены выше ищет файл под названием кофейный список.csv и анализирует каждый элемент строки в Кофейный объект .

Аналогичным образом, мы определяем писателя фасоли:

@Bean
public JdbcBatchItemWriter writer(DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder()
      .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
      .sql("INSERT INTO coffee (brand, origin, characteristics) VALUES (:brand, :origin, :characteristics)")
      .dataSource(dataSource)
      .build();
}

На этот раз мы включаем заявление S’L, необходимое для вставки одного элемента кофе в нашу базу данных, движимое свойствами фасоли Java нашей Кофейный объект. Удобно данныеИсточник автоматически создается @EnableBatchProcessing аннотация .

4.2. Составить нашу работу вместе

Наконец, нам нужно добавить фактические шаги задания и конфигурацию:

@Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
    return jobBuilderFactory.get("importUserJob")
      .incrementer(new RunIdIncrementer())
      .listener(listener)
      .flow(step1)
      .end()
      .build();
}

@Bean
public Step step1(JdbcBatchItemWriter writer) {
    return stepBuilderFactory.get("step1")
      . chunk(10)
      .reader(reader())
      .processor(processor())
      .writer(writer)
      .build();
}

@Bean
public CoffeeItemProcessor processor() {
    return new CoffeeItemProcessor();
}

Как мы видим, наша работа относительно проста и состоит из одного шага, определенного в step1 метод.

Давайте посмотрим на то, что этот шаг делает:

  • Во-первых, мы настраиваем наш шаг таким образом, чтобы он писал до десяти записей одновременно с помощью кусок (10) декларация
  • Затем мы читаем в кофе данных с помощью нашего читателя фасоли, которые мы устанавливаем с помощью читатель метод
  • Далее, мы переа проходим каждый из наших элементов кофе на пользовательский процессор, где мы применяем некоторые пользовательские бизнес-логики
  • Наконец, мы пишем каждый элемент кофе в базу данных, используя писателя мы видели ранее

С другой стороны, наши importUserJob содержит наше определение задания, которое содержит идентификатор с использованием системы RunIdИнкремент класса. Мы также установили JobCompletionNotificationListener, которые мы используем, чтобы получить уведомление, когда работа .

Чтобы завершить конфигурацию задания, мы перечисляем каждый шаг (хотя эта работа имеет только один шаг). Теперь у нас есть идеально настроенная работа!

5. Пользовательский кофе процессор

Давайте подробно рассмотрим пользовательский процессор, который мы определили ранее в нашей конфигурации работы:

public class CoffeeItemProcessor implements ItemProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class);

    @Override
    public Coffee process(final Coffee coffee) throws Exception {
        String brand = coffee.getBrand().toUpperCase();
        String origin = coffee.getOrigin().toUpperCase();
        String chracteristics = coffee.getCharacteristics().toUpperCase();

        Coffee transformedCoffee = new Coffee(brand, origin, chracteristics);
        LOGGER.info("Converting ( {} ) into ( {} )", coffee, transformedCoffee);

        return transformedCoffee;
    }
}

Особый интерес представляет ПунктПроцессор интерфейс предоставляет нам механизм для применения определенной бизнес-логики во время выполнения нашей работы.

Чтобы все было просто, мы определяем нашу КофеИтемПроцессор , который принимает входной Кофейный объект и преобразует каждый из свойств в верхний .

6. Завершение работы

Кроме того, мы также собираемся написать JobCompletionNotificationListener чтобы обеспечить обратную связь, когда наша работа заканчивается:

@Override
public void afterJob(JobExecution jobExecution) {
    if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
        LOGGER.info("!!! JOB FINISHED! Time to verify the results");

        String query = "SELECT brand, origin, characteristics FROM coffee";
        jdbcTemplate.query(query, (rs, row) -> new Coffee(rs.getString(1), rs.getString(2), rs.getString(3)))
          .forEach(coffee -> LOGGER.info("Found < {} > in the database.", coffee));
    }
}

В приведеном выше примере мы переопределяем afterJob метод и успешно проверить выполненную работу. Кроме того, мы запускаем тривиальный запрос, чтобы проверить, что каждый элемент кофе был успешно сохранен в базе данных .

7. Запуск нашей работы

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

...
17:41:16.336 [main] INFO  c.b.b.JobCompletionNotificationListener -
  !!! JOB FINISHED! Time to verify the results
17:41:16.336 [main] INFO  c.b.b.JobCompletionNotificationListener -
  Found < Coffee [brand=BLUE MOUNTAIN, origin=JAMAICA, characteristics=FRUITY] > in the database.
17:41:16.337 [main] INFO  c.b.b.JobCompletionNotificationListener -
  Found < Coffee [brand=LAVAZZA, origin=COLOMBIA, characteristics=STRONG] > in the database.
17:41:16.337 [main] INFO  c.b.b.JobCompletionNotificationListener -
  Found < Coffee [brand=FOLGERS, origin=AMERICA, characteristics=SMOKEY] > in the database.
...

Как мы видим, наша работа прошла успешно, и каждый элемент кофе хранился в базе данных, как и ожидалось .

8. Заключение

В этой статье мы узнали, как создать простую работу Spring Batch с помощью Spring Boot. Во-первых, мы начали с определения некоторых основных конфигураций.

Затем мы увидели, как добавить файл читателя и базы данных писателя. Наконец, мы приняли взглянуть на то, как применить некоторые пользовательские обработки и проверить нашу работу была выполнена успешно.

Как всегда, полный исходный код статьи доступен более на GitHub .