В этом посте я хочу показать, как вы можете использовать Spring Batch. Это пошаговое руководство по пакетному запуску Spring.
В корпоративных приложениях пакетная обработка является обычным явлением. Но по мере того, как данные становятся все более распространенными в Интернете, также становится важным, как мы обрабатываем эти данные. Существует множество доступных решений. Шторм Апачей или Apache Spark помогает с обработкой и преобразованием данных в требуемый формат. В этом посте мы более подробно рассмотрим Spring Batch.
Что такое Весенняя партия?
Spring Batch – это легкий фреймворк, предназначенный для облегчения пакетной обработки. Это позволяет разработчикам создавать пакетные приложения. В свою очередь, эти пакетные приложения обрабатывают поступающие данные и преобразуют их для дальнейшего использования.
Еще одним большим преимуществом использования Spring Batch является то, что он обеспечивает высокопроизводительную обработку этих данных. Для приложений, которые в значительной степени полагаются на данные, крайне важно, чтобы данные становились мгновенно доступными.
Spring Batch позволяет разработчику использовать подход, основанный на POJO. При таком подходе разработчик может преобразовать данные пакетной обработки в модели данных, которые он может в дальнейшем использовать для бизнес-логики приложения.
В этом посте я расскажу о примере, в котором мы будем пакетно обрабатывать CSV-файл с большим объемом данных для записей сотрудников и преобразовывать, проверять эти данные для загрузки в нашу базу данных.
Что такое Пакетная обработка?
Пакетная обработка – это режим обработки данных. Это включает в себя потребление всех данных, обработку этих данных, их преобразование и последующую отправку в другой источник данных. Обычно это делается с помощью автоматизированного задания. Либо запускающая система, либо пользователь запускают задание, и это задание обрабатывает определение задания. Определение задания будет касаться использования данных из их источника.
Ключевое преимущество пакетной обработки заключается в том, что она обрабатывает большой объем данных. Тем не менее, эта операция может быть асинхронной. Большинство приложений выполняют пакетную обработку отдельно от взаимодействия с пользователем в режиме реального времени.
Далее мы узнаем о Spring Batch framework и о том, что он включает в себя.
В следующей архитектуре показаны компоненты Spring Batch framework.
Во-первых, пакетный процесс включает в себя задание. Пользователь планирует выполнение задания в определенное время или на основе определенного условия. Это также может быть связано с запуском задания.
Пакет Spring Framework также включает в себя
- ведение журнала и отслеживание
- управление транзакциями
- статистика обработки заданий
- перезапуск задания
- управление ресурсами
Обычно, когда вы настраиваете задание, оно сохраняется в репозитории заданий. Хранилище заданий хранит метаданные всех заданий. Триггер запускает эти задания в назначенное время.
Средство запуска заданий
– это интерфейс для запуска задания или выполнения задания при наступлении запланированного времени выполнения заданий.
Задание
определяется с помощью параметров задания. Когда начинается задание, для этого задания запускается экземпляр задания. Каждое выполнение экземпляра задания имеет выполнение задания, и оно отслеживает статус задания. Задание может состоять из нескольких этапов.
Шаг
– это независимая фаза задания. Задание может состоять из более чем одного шага. Подобно заданию, каждый шаг имеет пошаговое выполнение, которое выполняет шаг и отслеживает статус шага.
На каждом шаге есть itemreader
, который в основном считывает входные данные, item processor
, который обрабатывает данные и преобразует их, и item writer
, который принимает обработанные данные и выводит их.
Теперь давайте посмотрим на все эти компоненты в нашей демонстрации.
Пошаговое руководство Spring Batch с примером
В рамках демонстрации мы будем загружать csv-файл через Spring Batch Framework. Итак, для начала создайте проект spring и добавьте следующую зависимость:
implementation 'org.springframework.boot:spring-boot-starter-batch'
Это основная зависимость нашего проекта. Также наше основное приложение будет выглядеть следующим образом:
package com.betterjavacode.springbatchdemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringbatchdemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbatchdemoApplication.class, args); } }
Создан ДЛЯ объекта
Я буду загружать данные о сотрудниках через CSV-файл, поэтому у меня будет создан объект DTO для сотрудника, как показано ниже:
package com.betterjavacode.springbatchdemo.dtos; import com.betterjavacode.springbatchdemo.models.Company; import com.betterjavacode.springbatchdemo.models.Employee; import com.betterjavacode.springbatchdemo.repositories.CompanyRepository; import org.springframework.beans.factory.annotation.Autowired; import java.io.Serializable; public class EmployeeDto implements Serializable { private static final long serialVersionUID = 710566148641281929L; @Autowired public CompanyRepository companyRepository; private int employeeId; private int companyId; private String firstName; private String lastName; private String email; private String jobTitle; public EmployeeDto() { } public EmployeeDto(int employeeId, String firstName, String lastName, String email, String jobTitle, int companyId) { this.employeeId = employeeId; this.firstName = firstName; this.lastName = lastName; this.email = email; this.jobTitle = jobTitle; this.companyId = companyId; } public Employee employeeDtoToEmployee() { Employee employee = new Employee(); employee.setEmployeeId(this.employeeId); employee.setFirstName(this.firstName); employee.setLastName(this.lastName); employee.setEmail(this.email); Company company = companyRepository.findById(this.companyId).get(); employee.setCompany(company); employee.setJobTitle(this.jobTitle); return employee; } public int getEmployeeId () { return employeeId; } public void setEmployeeId (int employeeId) { this.employeeId = employeeId; } public int getCompanyId () { return companyId; } public void setCompanyId (int companyId) { this.companyId = companyId; } 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; } public String getEmail () { return email; } public void setEmail (String email) { this.email = email; } public String getJobTitle () { return jobTitle; } public void setJobTitle (String jobTitle) { this.jobTitle = jobTitle; } }
Этот класс DTO также использует репозиторий Репозиторий компании
для получения объекта компании и преобразования В объект базы данных.
Настройка конфигурации пакета Spring
Теперь мы настроим пакетную конфигурацию для нашего задания, которое будет выполняться для загрузки CSV-файла в базу данных. Наш класс Пакетная конфигурация
содержит аннотацию @EnableBatchProcessing
. Эта аннотация включает функции пакетирования Spring и предоставляет базовую конфигурацию для настройки пакетных заданий в классе @Configuration
.
@Configuration @EnableBatchProcessing public class BatchConfig { }
Эта пакетная конфигурация будет включать определение нашей работы, этапы, связанные с выполнением работы. Он также будет включать в себя то, как мы хотим считывать данные нашего файла и обрабатывать их дальше.
@Bean public Job processJob(Step step) { return jobBuilderFactory.get("processJob") .incrementer(new RunIdIncrementer()) .listener(listener()) .flow(step).end().build(); } @Bean public Step orderStep1(JdbcBatchItemWriter writer) { return stepBuilderFactory.get("orderStep1").chunk(10) .reader(flatFileItemReader()) .processor(employeeItemProcessor()) .writer(writer).build(); }
Приведенный выше компонент объявляет задание process Job.incrementer
добавляет параметры задания. слушатель
будет прослушивать задание и обрабатывать статус задания. Компонент для прослушивателя будет обрабатывать уведомление о завершении задания или сбое задания. Как обсуждалось в Spring Batch architecture, каждое задание включает в себя более одного шага.
@Bean
для шага использует stepBuilderFactory
для создания шага. На этом шаге обрабатывается фрагмент данных размером 10. У него есть средство чтения плоских файлов FlatFileItemReader()
. Процессор employee ItemReader
будет обрабатывать данные, которые были прочитаны FlatFileItemReader.
@Bean public FlatFileItemReader flatFileItemReader() { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new ClassPathResource("input/employeedata.csv")) .delimited() .names(format) .linesToSkip(1) .lineMapper(lineMapper()) .fieldSetMapper(new BeanWrapperFieldSetMapper(){{ setTargetType(EmployeeDto.class); }}) .build(); } @Bean public LineMapper lineMapper() { final DefaultLineMapper defaultLineMapper = new DefaultLineMapper<>(); final DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer(); delimitedLineTokenizer.setDelimiter(","); delimitedLineTokenizer.setStrict(false); delimitedLineTokenizer.setNames(format); defaultLineMapper.setLineTokenizer(delimitedLineTokenizer); defaultLineMapper.setFieldSetMapper(employeeDtoFieldSetMapper); return defaultLineMapper; } @Bean public EmployeeItemProcessor employeeItemProcessor() { return new EmployeeItemProcessor(); } @Bean public JobExecutionListener listener() { return new JobCompletionListener(); } @Bean public JdbcBatchItemWriter writer(final DataSource dataSource) { return new JdbcBatchItemWriterBuilder() .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) .sql("INSERT INTO employee(employeeId, firstName, lastName, jobTitle, email, " + "companyId) VALUES(:employeeId, :firstName, :lastName, :jobTitle, :email," + " " + ":companyId)") .dataSource(dataSource) .build(); }
Сейчас мы рассмотрим каждый из этих бобов.
FlatFileItemReader
будет считывать данные из плоского файла. Мы используем конструктор FlatFileItemReader для создания FlatFileItemReader типа Employeedto.
ресурс
указывает местоположение файла.
разделенный
– Это создает токенизатор с разделителями.
имена
– покажет порядок полей в файле.
lineMapper
– это интерфейс для сопоставления строк из файла в объект домена.
FieldSetMapper
сопоставит данные из набора полей с объектом.
Linemapper
bean нуждается в tokenizer и fieldsetmapper.
доступ к FieldSetMapper
– это еще один компонент, который мы автоматически подключили в этом классе.
package com.betterjavacode.springbatchdemo.configurations.processor; import com.betterjavacode.springbatchdemo.dtos.EmployeeDto; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.stereotype.Component; import org.springframework.validation.BindException; @Component public class EmployeeDtoFieldSetMapper implements FieldSetMapper { @Override public EmployeeDto mapFieldSet (FieldSet fieldSet) throws BindException { int employeeId = fieldSet.readInt("employeeId"); String firstName = fieldSet.readRawString("firstName"); String lastName = fieldSet.readRawString("lastName"); String jobTitle = fieldSet.readRawString("jobTitle"); String email = fieldSet.readRawString("email"); int companyId = fieldSet.readInt("companyId"); return new EmployeeDto(employeeId, firstName, lastName, jobTitle, email, companyId); } }
Как вы можете видеть, этот FieldSetMapper сопоставляет поля отдельным объектам, чтобы создать Employee в
.
Сотрудник ItemProcessor
реализует интерфейс ItemProcessor. В основном в этом классе мы проверяем сотрудников на соответствие данным, чтобы проверить, существует ли компания, к которой принадлежит сотрудник.
Прослушиватель завершения задания
проверяет статус завершения задания.
@Override public void afterJob(JobExecution jobExecution) { if (jobExecution.getStatus() == BatchStatus.COMPLETED) { // Log statement System.out.println("BATCH JOB COMPLETED SUCCESSFULLY"); } }
Теперь давайте посмотрим на Item Writer
. Этот компонент в основном использует JdbcBatchItemWriter
. JdbcBatchItemWriter
использует инструкцию INSERT sql для вставки обработанных данных EMPLOYEEDTO в настроенный источник данных.
Настройка Свойств Приложения
Прежде чем мы запустим наше приложение для обработки файла, давайте посмотрим на application.properties
.
spring.datasource.url=jdbc:mysql://127.0.0.1/springbatchdemo?autoReconnect=true&useSSL=false spring.datasource.username = root spring.datasource.password=******* spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect spring.datasource.hikari.connection-test-query=SELECT 1 spring.batch.initialize-schema=ALWAYS
Помимо обычных свойств источника данных, мы должны понимать свойство spring.batch.initialize-schema= ВСЕГДА
. Если мы не используем это свойство и не запустим приложение, приложение будет жаловаться Таблица batch_job_instance не существует
.
Чтобы избежать этой ошибки, мы в основном рекомендуем создавать метаданные, связанные с пакетным заданием, во время запуска. Это свойство создаст дополнительные таблицы базы данных в вашей базе данных, такие как batch_job_execution
, batch_job_execution_context
, batch_job_execution_params
, batch_job_instance
и т.д.
Демонстрация
Теперь, если я выполню свое приложение Spring Boot, оно запустится и выполнит задание. Существуют разные способы запуска задания. В корпоративном приложении вы получите файл или данные в каком-либо хранилище (S3 или Amazon SNS-SQS), у вас будет задание, которое будет отслеживать это местоположение, чтобы запустить пакетное задание Spring для загрузки файлов.
При выполнении вы можете увидеть сообщение о завершении задания – “ПАКЕТНОЕ ЗАДАНИЕ УСПЕШНО ВЫПОЛНЕНО” . Если мы проверим нашу таблицу базы данных, мы увидим загруженные данные.
Вы можете скачать код для этой демонстрации из моего репозитория github .
Что еще?
Здесь я описал руководство по пакетному выпуску Spring, но это еще не все. В Spring Batch есть нечто большее, чем эта вводная часть. У вас могут быть разные источники входных данных, или вы также можете загружать данные из файла в файл с различными правилами обработки данных.
Существуют также способы автоматизации этих заданий и эффективной обработки большого объема данных.
Вывод
В этом посте я показал пошаговое руководство по Spring Batch. Существует много способов обработки пакетных заданий, но Spring Batch сделала это очень простым.
Из других новостей: недавно я выпустил свою новую книгу “Упрощение безопасности Spring”. Если вы хотите узнать больше о Spring Security, вы можете купить книгу здесь . Сопроводите эту книгу этим постом с вопросами для интервью Spring Boot и вы будете готовы к следующему собеседованию при приеме на работу.
Оригинал: “https://dev.to/betterjavacode/step-by-step-spring-batch-tutorial-go7”