SpringBoot~SpringBatch 使用

什么是Spring Batch

Spring Batch 是一個輕量級的、完善的批處理框架,旨在幫助企業建立健壯、高效的批處理應用。Spring Batch是Spring的一個子項目,使用Java語言并基于Spring框架為基礎開發,使的已經使用 Spring 框架的開發者或者企業更容易訪問和利用企業服務。
Spring Batch 提供了大量可重用的組件,包括了日志、追蹤、事務、任務作業統計、任務重啟、跳過、重復、資源管理。對于大數據量和高性能的批處理任務,Spring Batch 同樣提供了高級功能和特性來支持,比如分區功能、遠程功能。總之,通過 Spring Batch 能夠支持簡單的、復雜的和大數據量的批處理作業。

Spring Batch 使用

  1. 我們首先配置Spring Batch 在Spring Boot 中的使用,數據庫用的是mysql,pom文件如下,因為Spring Boot 中的Spring Batch 包含 hsqsldb 所以我們將其去除
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
            <exclusions> <!-- 注意這里-->
                <exclusion>
                    <groupId>org.hsqldb</groupId>
                    <artifactId>hsqldb</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
  1. 配置好我們需要的實體類。頁面就不展示了。
  2. 如果有數據校驗添加的話那么我們需要配置自定義的檢驗器。若果沒有課略過該步驟
public class CsvBeanValidator<T> implements Validator<T>,InitializingBean {

    private javax.validation.Validator    validator;

    @Override
    public void validate(T value) throws ValidationException {
        Set<ConstraintViolation<T >> constraintViolations=validator.validate(value);
        if(constraintViolations.size()>0){

            StringBuilder message=new StringBuilder();
            for(ConstraintViolation<T> constraintViolation:constraintViolations){
                message.append(constraintViolation.getMessage() +"\n");
            }
            throw  new ValidationException(message.toString());
        }


    }

    //在這里我們使用的是JSR-303校驗數據,在此進行初始化
    @Override
    public void afterPropertiesSet() throws Exception {  
        ValidatorFactory  validatorFactory= Validation.buildDefaultValidatorFactory();
        validator=validatorFactory.usingContext().getValidator();
    }
}

public class CsvItemProcessor extends ValidatingItemProcessor<Person> {


    @Override
    public Person process(Person item) throws ValidationException {
         super.process(item);  // 在這里啟動 然后才會調用我們自定義的校驗器,否則不能通過 。
         if (item.getNation().equals("漢族")){
             item.setName("01");
         }else{
             item.setNation("02");
         }
         return item;

    }
}

  1. 進行job任務監聽 自定義類實現JobExecutionListener 即可
    long startTime;
    long endTime;
    @Override
    public void beforeJob(JobExecution jobExecution) {
        startTime = System.currentTimeMillis();
        System.out.println("任務處理開始");
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        endTime = System.currentTimeMillis();
        System.out.println("耗時多長時間:" + (endTime - startTime) + "ms");
        System.out.println("任務處理結束");
    }

  1. 進行Spring Batch 的注入 方法有xml文件注入bean ,在這里選擇java注入
@Configuration
@EnableBatchProcessing  //開啟批處理
public class CsvBatchConfig {
      /**1 首先我們通過 FlatFileItemReader 讀取我們需要的文件 通過setResource來實現
        * 2 設置map  在這里通過先設置解析器 setLineTokenizer  來解析我們csv文件中的數     據
        * 3  setFieldSetMapper  將我們需要的數據轉化為我們的實體對象 存儲
        * 4 如果想 跳過前面的幾行 需要使用setLinesToSkip就可以實現 
         */ 
    @Bean
    public ItemReader<Person> reader() throws Exception {
        FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>(); //1
        reader.setResource(new ClassPathResource("people.csv")); //2
            reader.setLineMapper(new DefaultLineMapper<Person>() {{ //3
                setLineTokenizer(new DelimitedLineTokenizer() {{
                    setNames(new String[] { "name","age", "nation" ,"address"});
                }});
                setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                    setTargetType(Person.class);
                }});
            }});
                reader.setLinesToSkip(3);  
            return reader;
    }
    
    @Bean
    public ItemProcessor<Person, Person> processor() {
        CsvItemProcessor processor = new CsvItemProcessor(); //1
        processor.setValidator(csvBeanValidator()); //2
        return processor;
    }
    
    
        /** 
           *寫入數據到數據庫中
           * 1執行的sql 語句  2 設置數據源 
            */
    @Bean
    public ItemWriter<Person> writer(DataSource dataSource) {//1
        JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>(); //2
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
        String sql = "insert into person " + "(id,name,age,nation,address) "
                + "values(hibernate_sequence.nextval, :name, :age, :nation,:address)";
        writer.setSql(sql); //3
        writer.setDataSource(dataSource);
        return writer;
    }
     
      //  作業的倉庫 就是設置數據源
    @Bean
    public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager)
            throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        jobRepositoryFactoryBean.setDatabaseType("mysql");
        return jobRepositoryFactoryBean.getObject();
    }

        //調度器  使用它來執行 我們的批處理
    @Bean
    public SimpleJobLauncher jobLauncher(DataSource dataSource, PlatformTransactionManager transactionManager)
            throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository(dataSource, transactionManager));
        return jobLauncher;
    }

        //將監聽器加入到job中
    @Bean
    public Job importJob(JobBuilderFactory jobs, Step s1) {
        return jobs.get("importJob")
                .incrementer(new RunIdIncrementer())
                .flow(s1) //1
                .end()
                .listener(csvJobListener()) //2
                .build();
    }
        //步驟綁定 reader 與writer  一次性處理65000條記錄
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader<Person> reader, ItemWriter<Person> writer,
            ItemProcessor<Person,Person> processor) {
        return stepBuilderFactory
                .get("step1")
                .<Person, Person>chunk(65000) //1
                .reader(reader) //2
                .processor(processor) //3
                .writer(writer) //4
                .build();
    }



    @Bean
    public CsvJobListener csvJobListener() {
        return new CsvJobListener();
    }

    @Bean
    public Validator<Person> csvBeanValidator() {
        return new CsvBeanValidator<Person>();
    }
    

}

   
  1. 在配置文件中 啟動自動執行批處理
spring.batch.job.names = job1,job2 #啟動時要執行的Job,默認執行全部Job
spring.batch.job.enabled=true #是否自動執行定義的Job,默認是
spring.batch.initializer.enabled=true #是否初始化Spring Batch的數據庫,默認為是
spring.batch.schema=
spring.batch.table-prefix= #設置SpringBatch的數據庫表的前綴

項目匯總

從 項目中我們可以看到 總的步驟就是 首先讀取我們需要實現的文件進行解析,然后轉換成需要的實體類并且綁定到reader中,二 實現我們需要的writer 并且幫到到數據庫上,三實現job監聽器將其綁定到步驟中 。最后開啟批處理 自動執行入庫即可 。這個簡單步驟主要是配置中用到的 理解流程 自己也可以方便實現 批處理的流程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容