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

Введение в весеннюю партию

Краткое руководство по использованию Spring Batch для простого, но практичного сценария – перемещения некоторых данных из CSV в XML.

Автор оригинала: Eugen Paraschiv.

1. введение

В этой статье мы сосредоточимся на практическом, ориентированном на код введении в пакет Spring. Spring Batch – это платформа обработки, предназначенная для надежного выполнения заданий.

Текущая версия 4.3 поддерживает Spring 5 и Java 8. Он также поддерживает JSR-352, который является новой спецификацией java для пакетной обработки.

Вот несколько интересных и практических примеров использования фреймворка.

2. Основы рабочего процесса

Spring batch следует традиционной пакетной архитектуре, в которой репозиторий заданий выполняет работу по планированию и взаимодействию с заданием.

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

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

2.1. Наш Пример Использования

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

Входной файл имеет очень простую структуру – он содержит транзакцию в строке, состоящую из: имени пользователя, идентификатора пользователя, даты транзакции и суммы:

username, userid, transaction_date, transaction_amount
devendra, 1234, 31/10/2015, 10000
john, 2134, 3/12/2015, 12321
robin, 2134, 2/02/2015, 23411

3. Maven POM

Зависимости, необходимые для этого проекта, – это spring core, spring batch и sqlite jdbc connector:

        
        
            org.xerial
            sqlite-jdbc
            3.15.1
        
        
            org.springframework
            spring-oxm
            5.3.0
        
        
            org.springframework
            spring-jdbc
            5.3.0
        
        
            org.springframework.batch
            spring-batch-core
            4.3.0
        

4. Конфигурация пакета пружин

Первое, что мы сделаем, это настроим Spring Batch с помощью XML:

    
    
        
        
        
        
    

    
    
        
        
    

    
    

    
    
        
        
        
    

    

    
        
    

Конечно, конфигурация Java также доступна:

@Configuration
@EnableBatchProcessing
public class SpringConfig {

    @Value("org/springframework/batch/core/schema-drop-sqlite.sql")
    private Resource dropReopsitoryTables;

    @Value("org/springframework/batch/core/schema-sqlite.sql")
    private Resource dataReopsitorySchema;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.sqlite.JDBC");
        dataSource.setUrl("jdbc:sqlite:repository.sqlite");
        return dataSource;
    }

    @Bean
    public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
      throws MalformedURLException {
        ResourceDatabasePopulator databasePopulator = 
          new ResourceDatabasePopulator();

        databasePopulator.addScript(dropReopsitoryTables);
        databasePopulator.addScript(dataReopsitorySchema);
        databasePopulator.setIgnoreFailedDrops(true);

        DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource);
        initializer.setDatabasePopulator(databasePopulator);

        return initializer;
    }

    private JobRepository getJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(dataSource());
        factory.setTransactionManager(getTransactionManager());
        factory.afterPropertiesSet();
        return (JobRepository) factory.getObject();
    }

    private PlatformTransactionManager getTransactionManager() {
        return new ResourcelessTransactionManager();
    }

    public JobLauncher getJobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(getJobRepository());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }
}

5. Конфигурация пакетного задания Пружины

Давайте теперь напишем наше описание работы для работы CSV в XML:

    

    
    

        

        
            
                
                    
                        
                    
                
                
                    
                
            
        
    

    

    
        
        
        
    

    
        
            
                com.baeldung.spring_batch_intro.model.Transaction
            
        
    
    
        
            
                
                
            
        
    

И, конечно же, аналогичная конфигурация задания на основе Java:

public class SpringBatchConfig {
    
    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Value("input/record.csv")
    private Resource inputCsv;

    @Value("file:xml/output.xml")
    private Resource outputXml;

    @Bean
    public ItemReader itemReader()
      throws UnexpectedInputException, ParseException {
        FlatFileItemReader reader = new FlatFileItemReader();
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        String[] tokens = { "username", "userid", "transactiondate", "amount" };
        tokenizer.setNames(tokens);
        reader.setResource(inputCsv);
        DefaultLineMapper lineMapper = 
          new DefaultLineMapper();
        lineMapper.setLineTokenizer(tokenizer);
        lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
        reader.setLineMapper(lineMapper);
        return reader;
    }

    @Bean
    public ItemProcessor itemProcessor() {
        return new CustomItemProcessor();
    }

    @Bean
    public ItemWriter itemWriter(Marshaller marshaller)
      throws MalformedURLException {
        StaxEventItemWriter itemWriter = 
          new StaxEventItemWriter();
        itemWriter.setMarshaller(marshaller);
        itemWriter.setRootTagName("transactionRecord");
        itemWriter.setResource(outputXml);
        return itemWriter;
    }

    @Bean
    public Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setClassesToBeBound(new Class[] { Transaction.class });
        return marshaller;
    }

    @Bean
    protected Step step1(ItemReader reader,
      ItemProcessor processor,
      ItemWriter writer) {
        return steps.get("step1"). chunk(10)
          .reader(reader).processor(processor).writer(writer).build();
    }

    @Bean(name = "firstBatchJob")
    public Job job(@Qualifier("step1") Step step1) {
        return jobs.get("firstBatchJob").start(step1).build();
    }
}

Итак, теперь, когда у нас есть вся конфигурация, давайте разберем ее и начнем обсуждать.

5.1. Считывание Данных и создание объектов С помощью ItemReader

Сначала мы настроили cvsFileItemReader , который будет считывать данные из record.csv и преобразовывать их в Транзакцию объект:

@SuppressWarnings("restriction")
@XmlRootElement(name = "transactionRecord")
public class Transaction {
    private String username;
    private int userId;
    private LocalDateTime transactionDate;
    private double amount;

    /* getters and setters for the attributes */

    @Override
    public String toString() {
        return "Transaction [username=" + username + ", userId=" + userId
          + ", transactionDate=" + transactionDate + ", amount=" + amount
          + "]";
    }
}

Для этого – он использует пользовательский картограф:

public class RecordFieldSetMapper implements FieldSetMapper {
 
    public Transaction mapFieldSet(FieldSet fieldSet) throws BindException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyy");
        Transaction transaction = new Transaction();
 
        transaction.setUsername(fieldSet.readString("username"));
        transaction.setUserId(fieldSet.readInt(1));
        transaction.setAmount(fieldSet.readDouble(3));
        String dateString = fieldSet.readString(2);
        transaction.setTransactionDate(LocalDate.parse(dateString, formatter).atStartOfDay());
        return transaction;
    }
}

5.2. Обработка Данных С Помощью Обработчика Элементов

Мы создали наш собственный процессор элементов, CustomItemProcessor . Это не обрабатывает ничего, связанного с объектом транзакции – все, что он делает, это передает исходный объект, поступающий от читателя к записывающему устройству:

public class CustomItemProcessor implements ItemProcessor {

    public Transaction process(Transaction item) {
        return item;
    }
}

5.3. Запись объектов в ФС с помощью ItemWriter

Наконец, мы собираемся сохранить эту транзакцию в xml-файл, расположенный по адресу xml/output.xml :


    
    
    

5.4. Настройка пакетного задания

Поэтому все, что нам нужно сделать, это соединить точки с заданием, используя синтаксис batch:job .

Обратите внимание на интервал фиксации – это количество транзакций, которые должны храниться в памяти перед фиксацией пакета в ItemWriter ; он будет удерживать транзакции в памяти до этого момента (или до тех пор, пока не будет обнаружен конец входных данных):


    
        
            
            
        
    

5.5. Запуск пакетного задания

Вот и все – давайте теперь все настроим и запустим:

public class App {
    public static void main(String[] args) {
        // Spring Java config
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(SpringConfig.class);
        context.register(SpringBatchConfig.class);
        context.refresh();
        
        JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
        Job job = (Job) context.getBean("firstBatchJob");
        System.out.println("Starting the batch job");
        try {
            JobExecution execution = jobLauncher.run(job, new JobParameters());
            System.out.println("Job Status : " + execution.getStatus());
            System.out.println("Job completed");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Job failed");
        }
    }
}

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

Этот учебник дает вам базовое представление о том, как работать с Spring Batch и как использовать его в простом использовании.

В нем показано, как легко разработать конвейер пакетной обработки и как настроить различные этапы чтения, обработки и записи.

полную реализацию этого учебника можно найти в проекте github – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.