Вводный пример учебного примера Spring Batch

Spring Boot

Я покажу вам, как использоватьSpring BootсоздатьSpring BatchизHello WorldПример.

(шаг за шагом)

Итак, если выSpring Batchновички,Вам понравится это руководство.

Вы готовы?

Если вы хотите узнать больше оSpring Batchинформация, пожалуйста, посетитеУчебник по весенней пакетной обработкестраница.

1. Как работает среда Spring Batch

Перед погружением в код, давайте посмотримSpring BatchРамка.它包含以下主要构建块:

Spring Batch框架

ОдинBatch(пакетный) процесс состоит изJob(работа) состав. Этот объект инкапсулирует весь пакетный процесс.

ОдинJob(работа) может состоять из одного или несколькихStep(ступенчатая) композиция. В большинстве случаев шаг будет считывать данные (черезItemReader), Данные (использоватьItemProcessor), затем записать данные (поItemWriter).

JobLauncherПроцесс запускаетJob(Операция).

Наконец,JobRepositoryХранит информацию о конфигурации и выполненииJobМетаданные (домашнее задание).

для демонстрацииSpring BatchКак это работает, давайте создадим простое пакетное задание Hello World.

В этом примере мы从person.csvПрочитать имя и фамилию человека из файла. Создайте приветствие из этих данных. Тогда напишите это приветствиеgreeting .txtдокумент.

2. Пример обзора

Мы будем использовать следующие инструменты / рамки:

  • Spring Batch 4.1
  • Spring Boot 2.1
  • Maven 3.6

Структура каталогов нашего проекта выглядит следующим образом:

项目目录结构

3. Конфигурация Maven

Мы используемMavenСоберите и запустите пример. Если вы еще этого не сделали,Загрузите и установите Apache Maven..

давайте использоватьSpring Initializrдля создания проекта Maven. Убедитесь, что выбралиBatchкак зависимость.

image

нажмитеGenerate ProjectСоздайте и загрузите шаблон проекта Spring Boot. В корневом каталоге вашего проекта вы найдетеpom.xmlФайл, который является файлом конфигурации XML для проекта Maven.

Чтобы избежать необходимости управлять совместимостью версий различных зависимостей Spring, мы начнем сspring-boot-starter-parentРодительский POM наследует конфигурацию по умолчанию.

Созданный проект содержитSpring Boo StartersУправляет различными зависимостями Spring.

spring-boot-starter-batchИмпортироватьSpring BootиSpring Batchзависимости.

spring-boot-starter-testСодержит зависимости для тестирования приложений Spring Boot. он импортирует включениеJUnit,HamcrestиMockitoБиблиотеки включены.

Это также зависитspring-batch-test. Эта библиотека содержит несколько вспомогательных классов, которые помогут при тестировании пакетных заданий.

В разделе плагинов вы найдетеSpring Boot MavenПлагин:spring-boot-maven- plugin. Это помогает нам создать единую работоспособнуюuber-jar. Это удобный способ выполнения и публикации кода. Кроме того, плагин позволяет запускать пример с помощью команд Maven.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.codenotfound</groupId>
  <artifactId>spring-batch-hello-world</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-batch-hello-world</name>
  <description>Spring Batch Hello World Example</description>
  <url>https://codenotfound.com/spring-batch-example.html</url>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <java.version>11</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.batch</groupId>
      <artifactId>spring-batch-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

4. Конфигурация весенней загрузки

Мы используем Spring Boot, чтобы приложение Spring Batch «просто запускалось». Сначала создайтеSpringBatchApplicationсвоего рода. это содержитmain()Способ использованияSpring BootизSpringApplication.run()Запустите приложение.

Уведомление @SpringBootApplicationэто удобная аннотация, которая добавляет:@Configuration,@EnableAutoConfigurationи@ComponentScan.

Для получения дополнительной информации о Spring Boot см.Начало работы с Spring Boot.

по умолчанию,Spring BatchИспользуйте базу данных для хранения метаданных настроенных пакетных заданий.

В этом примере мы не используем базу данных напрямую, а используем отображение памяти на основеMap,бегатьSpring Batch.

spring-boot-starter-batch starterзависит отspring-boot-starter-jdbcи попытается создать экземпляр источника данных. Добавить кexclude = {DataSourceAutoConfiguration.class}добавлено в аннотации@SpringBootApplication. Это предотвращает автоматическую настройку Spring Boot для подключений к базе данных.DataSource.

package com.codenotfound;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringBatchApplication {

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

5. Создайте модель объекта

Перед обработкой данных часто желательно отображать его объектам объекта.

В моем примере входные данные хранятся вsrc/test/resources/csv/persons.csvв файле.

Каждая строка в файле содержит имя и фамилию через запятую.

John, Doe
Jane, Doe

Мы сопоставим эти данные сPersonобъект. Вот простое имя и фамилияPOJO.

package com.codenotfound.model;

public class Person {
  private String firstName;
  private String lastName;

  public Person() {
    // default constructor
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  @Override
  public String toString() {
    return firstName + " " + lastName;
  }
}

6. Настройте рабочую силу весны

Сначала мы создаемBatchConfigкласс, который будет настраивать Spring Batch. лучший в классе@ConfigurationАннотация указывает, что Spring может использовать этот класс в качестве источника для определений bean-компонентов.

мы добавили@EnableBatchProcessingаннотацию, поддерживающую все необходимыеSpring Batchхарактеристика.它还提供了设置批处理作业的基本配置。

Добавление этой аннотации потребует много операций. Ниже@EnableBatchProcessingСозданный обзор:

  • JobRepository (имя компонента "jobRepository")
  • JobLauncher (имя компонента "jobLauncher")
  • JobRegistry (имя компонента "jobRegistry")
  • JobExplorer (имя компонента "jobExplorer")
  • PlatformTransactionManager (Имя бобов »TransactionManager")
  • JobBuilderFactory (Имя бобов »(JoMbuilders»), его можно легко предотвратить, вы должны быть введены в каждый репозиторий работыJob(домашнее задание)
  • StepBuilderFactory (имя компонента "stepBuilders"), чтобы вы могли избежать внедрения репозитория заданий и менеджера транзакций в каждыйStep(шаг)

так какSpring BatchИспользовать на основе картыJobRepository, нам нужно продлитьDefaultBatchConfigurer. переписатьsetDataSource()способ не устанавливатьDataSource. Это приведет к автоматической настройкеИспользовать на основе картыJobRepository.

package com.codenotfound.batch;

import javax.sql.DataSource;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {

  @Override
  public void setDataSource(DataSource dataSource) {
    // initialize will use a Map based JobRepository (instead of database)
  }
}

Теперь перейдем к настройке задания Hello World Spring Batch.

СоздаватьHelloWorldJobConfigнастройте класс и добавьте его с помощью@Configurationаннотация.

существуетHelloWorldJobConfigБин, мы используемJobBuilderFactoryдля создания работы. мы доставляемJobНазвание (задания) и того, которое нужно запуститьStep(шаг).

УведомлениесуществуетhelloWorlJob()Бин,Spring автоматически введет jobBuildersиstepBuildersБобы.

существуетHelloWorldStepРазличные элементы, которые выполняет наш шаг, определены в bean-компоненте. Мы используемStepBuilderFactoryСоздайте шаг.

Во-первых, мы передаем имя шага. использоватьchunk(), мы указываем количество элементов, обрабатываемых в каждой транзакции. Чанк также указывает входные данные для шага (Person) и вывод (String)тип. Затем мы будемItemReader (reader),ItemProcessor (processor)иItemWriter (writer)Добавлено в шаг.

Мы используемFlatFileItemReaderПрочитайте CSV-файл человека. Этот класс предоставляет базовые функции для чтения и анализа файлов CSV.

существует одинFlatFileItemReaderBuilderреализация, позволяющая создатьFlatFileItemReader. Сначала мы указываем, что результатом чтения каждой строки в файле являетсяPersonобъект. Затем мы будем использоватьname()методFlatFileItemReaderДобавьте имя и укажите ресурс, который необходимо прочитать (в этом случае,persons.csvдокумент).

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

Мы также указываем, как сопоставить каждое поле в строке сPersonобъект. Это используетnames()Это делается путем создания полей карты Spring Batch путем сопоставления имени с установщиком объекта. В примере из этой статьи первое поле строки будет использоватьfirstNameсеттер для карты. Для этого нам также необходимо указатьtargetType,которыйPersonобъект.

Уведомление:

names(new String[] {"firstName", "lastName"})

PersonItemProcessorОбработка данных. Это будетPersonпреобразовать в приветствиеString. Мы определим его в отдельном классе ниже.

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

Мы используемFlatFileItemWriterBuilderреализация для созданияFlatFileItemWriter. мыwriterДобавьте имя и укажите ресурс, в который необходимо записать данные (в данном случаеgreeting.txtдокумент).

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

package com.codenotfound.batch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.file.transform.PassThroughLineAggregator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import com.codenotfound.model.Person;

@Configuration
public class HelloWorldJobConfig {

  @Bean
  public Job helloWorlJob(JobBuilderFactory jobBuilders,
      StepBuilderFactory stepBuilders) {
    return jobBuilders.get("helloWorldJob")
        .start(helloWorldStep(stepBuilders)).build();
  }

  @Bean
  public Step helloWorldStep(StepBuilderFactory stepBuilders) {
    return stepBuilders.get("helloWorldStep")
        .<Person, String>chunk(10).reader(reader())
        .processor(processor()).writer(writer()).build();
  }

  @Bean
  public FlatFileItemReader<Person> reader() {
    return new FlatFileItemReaderBuilder<Person>()
        .name("personItemReader")
        .resource(new ClassPathResource("csv/persons.csv"))
        .delimited().names(new String[] {"firstName", "lastName"})
        .targetType(Person.class).build();
  }

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

  @Bean
  public FlatFileItemWriter<String> writer() {
    return new FlatFileItemWriterBuilder<String>()
        .name("greetingItemWriter")
        .resource(new FileSystemResource(
            "target/test-outputs/greetings.txt"))
        .lineAggregator(new PassThroughLineAggregator<>()).build();
  }
}

7. Обработка данных

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

В нашем примере мы будемPersonПреобразование объекта в простое приветствиеString

Для этого создадим реализациюItemProcessorинтерфейсPersonItemProcessor. мы достиглиprocess()метод, который добавляет в строку имя и фамилию человека.

В процессе отладки мы записываем результаты в лог.

package com.codenotfound.batch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import com.codenotfound.model.Person;

public class PersonItemProcessor
    implements ItemProcessor<Person, String> {

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

  @Override
  public String process(Person person) throws Exception {
    String greeting = "Hello " + person.getFirstName() + " "
        + person.getLastName() + "!";

    LOGGER.info("converting '{}' into '{}'", person, greeting);
    return greeting;
  }
}

8. Протестируйте пример Spring Batch

Чтобы протестировать этот пример, мы создали базовый модульный тестовый пример. Он запустит пакетное задание и проверит его успешное завершение.

Мы используем@RunWithи@SpringBootTestтестовая аннотацияРассказыватьJUnitРаботает с тестовой поддержкой Spring и начальной загрузкой с поддержкой Spring Boot.

Spring Batchпоставляется с однимJobLauncherTestUtilsУтилита классов для тестирования пакетной задачи.

Начнем с создания внутреннегоBatchTestConfigкласс, добавьте задание helloWorld вJobLauncherTestUtilsбоб. затем используйте этот beanlaunchJob()способ запуска пакетного задания.

Если задание выполняется без ошибок, тоExitCodeзначениеCOMPLETED.

package com.codenotfound;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import com.codenotfound.batch.job.BatchConfig;
import com.codenotfound.batch.job.HelloWorldJobConfig;

@RunWith(SpringRunner.class)
@SpringBootTest(
    classes = {SpringBatchApplicationTests.BatchTestConfig.class})
public class SpringBatchApplicationTests {

  @Autowired
  private JobLauncherTestUtils jobLauncherTestUtils;

  @Test
  public void testHelloWorldJob() throws Exception {
    JobExecution jobExecution = jobLauncherTestUtils.launchJob();
    assertThat(jobExecution.getExitStatus().getExitCode())
        .isEqualTo("COMPLETED");
  }

  @Configuration
  @Import({BatchConfig.class, HelloWorldJobConfig.class})
  static class BatchTestConfig {

    @Autowired
    private Job helloWorlJob;

    @Bean
    JobLauncherTestUtils jobLauncherTestUtils()
        throws NoSuchJobException {
      JobLauncherTestUtils jobLauncherTestUtils =
          new JobLauncherTestUtils();
      jobLauncherTestUtils.setJob(helloWorlJob);

      return jobLauncherTestUtils;
    }
  }
}

Чтобы запустить приведенный выше тестовый пример, откройте командную строку в корневой папке проекта и выполните следующие действия.MavenЗаказ:

mvn test

В результате сборка завершается успешно, а пакетное задание тем временем выполняется.

 .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
 '  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::        (v2.1.5.RELEASE)

2019-05-30 19:11:12.784  INFO 14588 --- [           main] c.c.SpringBatchApplicationTests          : Starting SpringBatchApplicationTests on DESKTOP-2RB3C1U with PID 14588 (started by Codenotfound in C:\Users\Codenotfound\repos\spring-batch\spring-batch-hello-world)
2019-05-30 19:11:12.785  INFO 14588 --- [           main] c.c.SpringBatchApplicationTests          : No active profile set, falling back to default profiles: default
2019-05-30 19:11:13.305  WARN 14588 --- [           main] o.s.b.c.c.a.DefaultBatchConfigurer       : No datasource was provided...using a Map based JobRepository
2019-05-30 19:11:13.306  WARN 14588 --- [           main] o.s.b.c.c.a.DefaultBatchConfigurer       : No transaction manager was provided, using a ResourcelessTransactionManager
2019-05-30 19:11:13.328  INFO 14588 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2019-05-30 19:11:13.350  INFO 14588 --- [           main] c.c.SpringBatchApplicationTests          : Started SpringBatchApplicationTests in 0.894 seconds (JVM running for 1.777)
2019-05-30 19:11:13.732  INFO 14588 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=helloWorldJob]] launched with the following parameters: [{random=459672}]
2019-05-30 19:11:13.759  INFO 14588 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [helloWorldStep]
2019-05-30 19:11:13.812  INFO 14588 --- [           main] c.c.batch.PersonItemProcessor            : converting 'John Doe' into 'Hello John Doe!'
2019-05-30 19:11:13.822  INFO 14588 --- [           main] c.c.batch.PersonItemProcessor            : converting 'Jane Doe' into 'Hello Jane Doe!'
2019-05-30 19:11:13.842  INFO 14588 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=helloWorldJob]] completed with the following parameters: [{random=459672}] and the following status: [COMPLETED]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.953 s - in com.codenotfound.SpringBatchApplicationTests
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.852 s
[INFO] Finished at: 2019-05-30T19:11:14+02:00
[INFO] ------------------------------------------------------------------------

ты сможешьtarget/test-output /greeting .txtРезультаты найдены в файле:

Hello John Doe!
Hello Jane Doe!

Если вы хотите запустить приведенный выше пример кода, вы можете получить полныйисходный код.

В этом вводном руководстве вы узнали, как создать простой пример Spring Batch с использованием Spring Boot и Maven.

Оригинальная ссылка:code not found.com/spring - самое главное…

Добавить Автора

Переводчик:Ли Донг