В этом посте я хочу показать, как вы можете использовать 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”