溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Batch的概念和作用是什么

發(fā)布時(shí)間:2021-06-22 17:56:11 來源:億速云 閱讀:224 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Spring Batch的概念和作用是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Batch的概念和作用是什么”吧!

目錄
  • 一、Spring Batch的概念知識

    • 1.1、分層架構(gòu)

    • 1.2、關(guān)鍵概念

      • 1.2.1、JobRepository

      • 1.2.2、任務(wù)啟動器JobLauncher

      • 1.2.3、任務(wù)Job

      • 1.2.4、步驟Step

      • 1.2.5、輸入——處理——輸出

  • 二、代碼實(shí)例

    • 2.1、基本框架

      • 2.2、輸入——處理——輸出

        • 2.2.1、讀取ItemReader

        • 2.2.2、處理ItemProcessor

        • 2.2.3、輸出ItremWriter

      • 2.3、Step

        • 2.4、Job

          • 2.5、運(yùn)行

          • 三、監(jiān)聽Listener

            一、Spring Batch的概念知識

            1.1、分層架構(gòu)

            Spring Batch的分層架構(gòu)圖如下:

            Spring Batch的概念和作用是什么

            可以看到它分為三層,分別是:

            • Application應(yīng)用層:包含了所有任務(wù)batch jobs和開發(fā)人員自定義的代碼,主要是根據(jù)項(xiàng)目需要開發(fā)的業(yè)務(wù)流程等。

            • Batch Core核心層:包含啟動和管理任務(wù)的運(yùn)行環(huán)境類,如JobLauncher等。

            • Batch Infrastructure基礎(chǔ)層:上面兩層是建立在基礎(chǔ)層之上的,包含基礎(chǔ)的讀入reader寫出writer、重試框架等。

            1.2、關(guān)鍵概念

            理解下圖所涉及的概念至關(guān)重要,不然很難進(jìn)行后續(xù)開發(fā)和問題分析。

            Spring Batch的概念和作用是什么

            1.2.1、JobRepository

            專門負(fù)責(zé)與數(shù)據(jù)庫打交道,對整個(gè)批處理的新增、更新、執(zhí)行進(jìn)行記錄。所以Spring Batch是需要依賴數(shù)據(jù)庫來管理的。

            1.2.2、任務(wù)啟動器JobLauncher

            負(fù)責(zé)啟動任務(wù)Job

            1.2.3、任務(wù)Job

            Job是封裝整個(gè)批處理過程的單位,跑一個(gè)批處理任務(wù),就是跑一個(gè)Job所定義的內(nèi)容。

            Spring Batch的概念和作用是什么

            上圖介紹了Job的一些相關(guān)概念:

            • Job:封裝處理實(shí)體,定義過程邏輯。

            • JobInstanceJob的運(yùn)行實(shí)例,不同的實(shí)例,參數(shù)不同,所以定義好一個(gè)Job后可以通過不同參數(shù)運(yùn)行多次。

            • JobParameters:與JobInstance相關(guān)聯(lián)的參數(shù)。

            • JobExecution:代表Job的一次實(shí)際執(zhí)行,可能成功、可能失敗。

            所以,開發(fā)人員要做的事情,就是定義Job

            1.2.4、步驟Step

            Step是對Job某個(gè)過程的封裝,一個(gè)Job可以包含一個(gè)或多個(gè)Step,一步步的Step按特定邏輯執(zhí)行,才代表Job執(zhí)行完成。

            Spring Batch的概念和作用是什么

            通過定義Step來組裝Job可以更靈活地實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯。

            1.2.5、輸入——處理——輸出

            所以,定義一個(gè)Job關(guān)鍵是定義好一個(gè)或多個(gè)Step,然后把它們組裝好即可。而定義Step有多種方法,但有一種常用的模型就是輸入——處理——輸出,即Item ReaderItem ProcessorItem Writer。比如通過Item Reader從文件輸入數(shù)據(jù),然后通過Item Processor進(jìn)行業(yè)務(wù)處理和數(shù)據(jù)轉(zhuǎn)換,最后通過Item Writer寫到數(shù)據(jù)庫中去。

            Spring Batch為我們提供了許多開箱即用的ReaderWriter,非常方便。

            二、代碼實(shí)例

            理解了基本概念后,就直接通過代碼來感受一下吧。整個(gè)項(xiàng)目的功能是從多個(gè)csv文件中讀數(shù)據(jù),處理后輸出到一個(gè)csv文件。

            2.1、基本框架

            添加依賴:

            <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-batch</artifactId>
            </dependency>
            <dependency>
              <groupId>com.h3database</groupId>
              <artifactId>h3</artifactId>
              <scope>runtime</scope>
            </dependency>

            需要添加Spring Batch的依賴,同時(shí)使用H2作為內(nèi)存數(shù)據(jù)庫比較方便,實(shí)際生產(chǎn)肯定是要使用外部的數(shù)據(jù)庫,如Oracle、PostgreSQL。

            入口主類:

            @SpringBootApplication
            @EnableBatchProcessing
            public class PkslowBatchJobMain {
                public static void main(String[] args) {
                    SpringApplication.run(PkslowBatchJobMain.class, args);
                }
            }

            也很簡單,只是在Springboot的基礎(chǔ)上添加注解@EnableBatchProcessing。

            領(lǐng)域?qū)嶓w類Employee

            package com.pkslow.batch.entity;
            public class Employee {
                String id;
                String firstName;
                String lastName;
            }

            對應(yīng)的csv文件內(nèi)容如下:

            id,firstName,lastName

            1,Lokesh,Gupta

            2,Amit,Mishra

            3,Pankaj,Kumar

            4,David,Miller

            2.2、輸入——處理——輸出

            2.2.1、讀取ItemReader

            因?yàn)橛卸鄠€(gè)輸入文件,所以定義如下:

            @Value("input/inputData*.csv")
            private Resource[] inputResources;
            
            @Bean
            public MultiResourceItemReader<Employee> multiResourceItemReader()
            {
              MultiResourceItemReader<Employee> resourceItemReader = new MultiResourceItemReader<Employee>();
              resourceItemReader.setResources(inputResources);
              resourceItemReader.setDelegate(reader());
              return resourceItemReader;
            }
            
            @Bean
            public FlatFileItemReader<Employee> reader()
            {
              FlatFileItemReader<Employee> reader = new FlatFileItemReader<Employee>();
              //跳過csv文件第一行,為表頭
              reader.setLinesToSkip(1);
              reader.setLineMapper(new DefaultLineMapper() {
                {
                  setLineTokenizer(new DelimitedLineTokenizer() {
                    {
                      //字段名
                      setNames(new String[] { "id", "firstName", "lastName" });
                    }
                  });
                  setFieldSetMapper(new BeanWrapperFieldSetMapper<Employee>() {
                    {
                      //轉(zhuǎn)換化后的目標(biāo)類
                      setTargetType(Employee.class);
                    }
                  });
                }
              });
              return reader;
            }

            這里使用了FlatFileItemReader,方便我們從文件讀取數(shù)據(jù)。

            2.2.2、處理ItemProcessor

            為了簡單演示,處理很簡單,就是把最后一列轉(zhuǎn)為大寫:

            public ItemProcessor<Employee, Employee> itemProcessor() {
              return employee -> {
                employee.setLastName(employee.getLastName().toUpperCase());
                return employee;
              };
            }
            2.2.3、輸出ItremWriter

            比較簡單,代碼及注釋如下:

            private Resource outputResource = new FileSystemResource("output/outputData.csv");
            
            @Bean
            public FlatFileItemWriter<Employee> writer()
            {
              FlatFileItemWriter<Employee> writer = new FlatFileItemWriter<>();
              writer.setResource(outputResource);
              //是否為追加模式
              writer.setAppendAllowed(true);
              writer.setLineAggregator(new DelimitedLineAggregator<Employee>() {
                {
                  //設(shè)置分割符
                  setDelimiter(",");
                  setFieldExtractor(new BeanWrapperFieldExtractor<Employee>() {
                    {
                      //設(shè)置字段
                      setNames(new String[] { "id", "firstName", "lastName" });
                    }
                  });
                }
              });
              return writer;
            }

            2.3、Step

            有了Reader-Processor-Writer后,就可以定義Step了:

            @Bean
            public Step csvStep() {
              return stepBuilderFactory.get("csvStep").<Employee, Employee>chunk(5)
                .reader(multiResourceItemReader())
                .processor(itemProcessor())
                .writer(writer())
                .build();
            }

            這里有一個(gè)chunk的設(shè)置,值為5,意思是5條記錄后再提交輸出,可以根據(jù)自己需求定義。

            2.4、Job

            完成了Step的編碼,定義Job就容易了:

            @Bean
            public Job pkslowCsvJob() {
              return jobBuilderFactory
                .get("pkslowCsvJob")
                .incrementer(new RunIdIncrementer())
                .start(csvStep())
                .build();
            }

            2.5、運(yùn)行

            完成以上編碼后,執(zhí)行程序,結(jié)果如下:

            Spring Batch的概念和作用是什么

            成功讀取數(shù)據(jù),并將最后字段轉(zhuǎn)為大寫,并輸出到outputData.csv文件。

            三、監(jiān)聽Listener

            可以通過Listener接口對特定事件進(jìn)行監(jiān)聽,以實(shí)現(xiàn)更多業(yè)務(wù)功能。比如如果處理失敗,就記錄一條失敗日志;處理完成,就通知下游拿數(shù)據(jù)等。

            我們分別對Read、ProcessWrite事件進(jìn)行監(jiān)聽,對應(yīng)分別要實(shí)現(xiàn)ItemReadListener接口、ItemProcessListener接口和ItemWriteListener接口。因?yàn)榇a比較簡單,就是打印一下日志,這里只貼出ItemWriteListener的實(shí)現(xiàn)代碼:

            public class PkslowWriteListener implements ItemWriteListener<Employee> {
                private static final Log logger = LogFactory.getLog(PkslowWriteListener.class);
                @Override
                public void beforeWrite(List<? extends Employee> list) {
                    logger.info("beforeWrite: " + list);
                }
            
                @Override
                public void afterWrite(List<? extends Employee> list) {
                    logger.info("afterWrite: " + list);
                }
            
                @Override
                public void onWriteError(Exception e, List<? extends Employee> list) {
                    logger.info("onWriteError: " + list);
                }
            }

            把實(shí)現(xiàn)的監(jiān)聽器listener整合到Step中去:

            @Bean
            public Step csvStep() {
              return stepBuilderFactory.get("csvStep").<Employee, Employee>chunk(5)
                .reader(multiResourceItemReader())
                .listener(new PkslowReadListener())
                .processor(itemProcessor())
                .listener(new PkslowProcessListener())
                .writer(writer())
                .listener(new PkslowWriteListener())
                .build();
            }

            執(zhí)行后看一下日志:

            Spring Batch的概念和作用是什么

            這里就能明顯看到之前設(shè)置的chunk的作用了。Writer每次是處理5條記錄,如果一條輸出一次,會對IO造成壓力。

            感謝各位的閱讀,以上就是“Spring Batch的概念和作用是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring Batch的概念和作用是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

            向AI問一下細(xì)節(jié)

            免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

            AI