您好,登錄后才能下訂單哦!
這篇文章主要介紹“Spring Batch 的原理和作用”,在日常操作中,相信很多人在Spring Batch 的原理和作用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spring Batch 的原理和作用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
1.Spring Batch框架工作原理
2.示例概述
3. Maven配置
4. Spring Boot 配置
5. 創建實體模型
6. 配置 Spring Batch Job
7. 處理數據
8.測試Spring Batch 示例
我將向您展示如何使用Spring Boot
創建一個的Spring Batch
的Hello World
示例。
(循序漸進)
因此,如果您是Spring Batch
的初學者,您一定會喜歡本指南。
準備好了嗎?
如果您想了解更多關于Spring Batch
的信息,請訪問
Spring Batch教程頁面。
在深入研究代碼之前,讓我們先看看Spring Batch
框架。它包含以下主要構建塊:
一個Batch
(批處理)過程由一個Job
(作業)組成。這個實體封裝了整個批處理過程。
一個Job
(作業)可以由一個或多個Step
(步驟)組成。在大多數情況下,一個步驟將讀取數據(通過ItemReader
),處理數據(使用ItemProcessor
),然后寫入數據(通過ItemWriter
)。
JobLauncher
處理啟動一個Job
(作業)。
最后,JobRepository
存儲關于配置和執行的Job
(作業)的元數據。
為了演示Spring Batch
是如何工作的,讓我們構建一個簡單的Hello World批處理作業。
在本例中,我們從person.csv
文件中讀取一個人的姓和名。從這些數據生成一個問候語。然后將此問候語寫入greeting .txt
文件。
我們會使用以下工具/框架:
Spring Batch 4.1
Spring Boot 2.1
Maven 3.6
我們的項目目錄結構如下:
我們使用Maven構建并運行示例。如果還沒有,下載并安裝Apache Maven。
讓我們使用Spring Initializr來生成Maven項目。確保選擇Batch
作為依賴項。
單擊Generate Project
生成并下載Spring Boot項目模板。在項目的根目錄中,您將發現一個pom.xml
文件,它是Maven項目的XML配置文件。
為了避免必須管理不同Spring依賴項的版本兼容性,我們將從spring-boot-starter-parent
父POM繼承默認配置。
生成的項目包含Spring Boo Starters管理著不同的Spring依賴項。
spring-boot-starter-batch
導入Spring Boot
和Spring Batch
依賴項。
spring-boot-starter-test
包含用于測試Spring引導應用程序的依賴項。它導入了包括JUnit、Hamcrest和Mockito在內的庫。
這個也有依賴性spring-batch-test
。這個庫包含一些幫助類,它們將幫助測試批處理作業。
在plugins部分,您將找到Spring Boot Maven插件:spring-boot-maven- plugin
。它幫助我們構建一個單一的、可運行的uber-jar
。這是執行和發布代碼的一種方便方法。此外,插件允許您通過Maven命令啟動示例。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.codenotfound</groupId> <artifactId>spring-batch-hello-world</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-batch-hello-world</name> <description>Spring Batch Hello World Example</description> <url>https://codenotfound.com/spring-batch-example.html</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
我們使用Spring Boot,目的是讓一個Spring Batch應用程序可以“直接運行”。
首先創建一個SpringBatchApplication
類。它包含main()
方法,該方法使用Spring Boot
的SpringApplication.run()
啟動應用程序。
注意@SpringBootApplication
是一個方便的注解,它添加了:@Configuration
、@EnableAutoConfiguration
和@ComponentScan
。
有關Spring Boot的更多信息,請查看Spring Boot入門指南。
默認情況下,Spring Batch
使用數據庫存儲已配置的批處理作業上的元數據。
在本例中,我們不直接使用數據庫,而是使用基于內存映射的Map
,運行Spring Batch
。
spring-boot-starter-batch starter
依賴于spring-boot-starter-jdbc
,并將嘗試實例化數據源。添加 exclude = {DataSourceAutoConfiguration.class}
注解中添加@SpringBootApplication
。這可以防止Spring Boot為數據庫連接自動配置DataSource
。
package com.codenotfound; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class SpringBatchApplication { public static void main(String[] args) { SpringApplication.run(SpringBatchApplication.class, args); } }
在處理數據之前,通常希望將其映射到實體對象。
在我的示例中,輸入數據存儲在src/test/resources/csv/persons.csv
文件中。
文件中的每一行都包含一個逗號分隔的姓和名。
John, Doe
Jane, Doe
我們將把這個數據映射到Person
對象。這是一個包含姓和名的簡單POJO。
package com.codenotfound.model; public class Person { private String firstName; private String lastName; public Person() { // default constructor } 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; } @Override public String toString() { return firstName + " " + lastName; } }
我們首先創建一個BatchConfig
類,它將配置Spring Batch。類頂部的@Configuration注解表明Spring可以使用該類作為bean定義的源。
我們添加了@EnableBatchProcessing注解,它支持所有所需Spring Batch
特性。它還提供了設置批處理作業的基本配置。
通過添加這個注解會需要很多操作。下面是@EnableBatchProcessing
創建的概述:
JobRepository (bean名稱 "jobRepository")
JobLauncher (bean名稱 "jobLauncher")
JobRegistry (bean名稱 "jobRegistry")
JobExplorer (bean名稱 "jobExplorer")
PlatformTransactionManager (bean名稱 "transactionManager")
JobBuilderFactory (bean名稱"jobBuilders"),它可以方便地防止您必須將作業存儲庫注入到每個Job(作業)中
StepBuilderFactory (bean名稱 "stepBuilders"),以方便您避免將作業存儲庫和事務管理器注入到每個Step(步驟)中
為了使Spring Batch
使用基于Map的JobRepository
,我們需要擴展DefaultBatchConfigurer
。重寫setDataSource()
方法以不設置DataSource
。這將導致自動配置使用基于Map的JobRepository
。
package com.codenotfound.batch; import javax.sql.DataSource; import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.context.annotation.Configuration; @Configuration@EnableBatchProcessingpublic class BatchConfig extends DefaultBatchConfigurer { @Override public void setDataSource(DataSource dataSource) { // initialize will use a Map based JobRepository (instead of database) } }
現在讓我們繼續配置Hello World Spring Batch 作業。
創建一個HelloWorldJobConfig
配置類,并用添加@Configuration
注解。
在HelloWorldJobConfig
Bean中,我們使用JobBuilderFactory
來創建作業。我們傳遞Job
(作業)的名稱和需要運行的Step
(步驟)。
注意
在helloWorlJob()
Bean中,Spring將自動注入 jobBuilders
和 stepBuilders
Beans。
在HelloWorldStep
Bean中定義了我們的步驟執行的不同項。我們使用StepBuilderFactory
創建步驟。
首先,我們傳入步驟的名稱。使用chunk()
,我們指定每個事務中處理的項的數量。Chunk還指定步驟的輸入(Person
)和輸出(String
)類型。然后,我們將ItemReader (reader)
、ItemProcessor (processor)
和ItemWriter (writer)
添加到步驟中。
我們使用FlatFileItemReader讀取person CSV文件。這個類提供了讀取和解析CSV文件的基本功能。
有一個FlatFileItemReaderBuilder
實現,它允許我們創建一個FlatFileItemReader
。我們首先指定讀取文件中每一行的結果是Person
對象。然后,我們將使用name()
方法為FlatFileItemReader
添加一個名稱,并指定需要讀取的資源(在本例中是persons.csv
文件)。
為了讓FlatFileItemReader
處理我們的文件,我們需要指定一些額外的信息。首先,我們定義文件中的數據是帶分隔符的(默認為逗號作為分隔符)。
我們還指定了如何將一行中的每個字段映射到Person
對象。這是使用names()
來完成的,通過將名稱與對象上的setter匹配,可以使Spring Batch映射字段。
在本文的例子中,一行的第一個字段將使用firstName
setter進行映射。為了實現這一點,我們還需要指定targetType
,即Person
對象。
注意:
names(new String[] {"firstName", "lastName"})
PersonItemProcessor
處理數據。它將一個Person
轉換成一個問候String
。我們將在下面的一個單獨的類中定義它。
一旦數據被處理,我們將把它寫入一個文本文件。我們使用FlatFileItemWriter
來完成這項任務。
我們使用FlatFileItemWriterBuilder
實現來創建一個FlatFileItemWriter
。我們為writer
添加一個名稱,并指定需要將數據寫入其中的資源(在本例中是greeting.txt
文件)。
FlatFileItemWriter
需要知道如何將生成的輸出轉換成可以寫入文件的單個字符串。在本例中,我們的輸出已經是一個字符串,我們可以使用PassThroughLineAggregator
。這是最基本的實現,它假定對象已經是一個字符串。
package com.codenotfound.batch; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.FlatFileItemWriter; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder; import org.springframework.batch.item.file.transform.PassThroughLineAggregator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import com.codenotfound.model.Person; @Configurationpublic class HelloWorldJobConfig { @Bean public Job helloWorlJob(JobBuilderFactory jobBuilders, StepBuilderFactory stepBuilders) { return jobBuilders.get("helloWorldJob") .start(helloWorldStep(stepBuilders)).build(); } @Bean public Step helloWorldStep(StepBuilderFactory stepBuilders) { return stepBuilders.get("helloWorldStep") .<Person, String>chunk(10).reader(reader()) .processor(processor()).writer(writer()).build(); } @Bean public FlatFileItemReader<Person> reader() { return new FlatFileItemReaderBuilder<Person>() .name("personItemReader") .resource(new ClassPathResource("csv/persons.csv")) .delimited().names(new String[] {"firstName", "lastName"}) .targetType(Person.class).build(); } @Bean public PersonItemProcessor processor() { return new PersonItemProcessor(); } @Bean public FlatFileItemWriter<String> writer() { return new FlatFileItemWriterBuilder<String>() .name("greetingItemWriter") .resource(new FileSystemResource( "target/test-outputs/greetings.txt")) .lineAggregator(new PassThroughLineAggregator<>()).build(); } }
在大多數情況下,您將希望在批處理作業期間應用一些數據處理。可以使用ItemProcessor來操作。
在我們的示例中,我們將Person
對象轉換為一個簡單的問候語String
為此,我們創建一個實現ItemProcessor
接口的PersonItemProcessor
。我們實現了process()
方法,它將人名和姓氏添加到字符串中。
調試的過程中,我們記錄日志結果。
package com.codenotfound.batch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemProcessor; import com.codenotfound.model.Person; public class PersonItemProcessor implements ItemProcessor<Person, String> { private static final Logger LOGGER = LoggerFactory.getLogger(PersonItemProcessor.class); @Override public String process(Person person) throws Exception { String greeting = "Hello " + person.getFirstName() + " " + person.getLastName() + "!"; LOGGER.info("converting '{}' into '{}'", person, greeting); return greeting; } }
為了測試本的例子,我們創建了一個基本的單元測試用例。它將運行批處理作業并檢查是否成功完成。
我們使用@RunWith
和@SpringBootTest
測試注解告訴JUnit
使用Spring的測試支持運行,并使用SpringBoot的支持引導。
Spring Batch
附帶一個JobLauncherTestUtils
實用程序類,用于測試批處理作業。
我們首先創建一個內部BatchTestConfig
類,將helloWorld作業添加到JobLauncherTestUtils
bean中。然后使用此bean的launchJob()
方法運行批處理作業。
如果執行的作業沒有任何錯誤,則ExitCode
的值為COMPLETED
。
package com.codenotfound; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.launch.NoSuchJobException; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; import com.codenotfound.batch.job.BatchConfig; import com.codenotfound.batch.job.HelloWorldJobConfig; @RunWith(SpringRunner.class) @SpringBootTest( classes = {SpringBatchApplicationTests.BatchTestConfig.class}) public class SpringBatchApplicationTests { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test public void testHelloWorldJob() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); assertThat(jobExecution.getExitStatus().getExitCode()) .isEqualTo("COMPLETED"); } @Configuration @Import({BatchConfig.class, HelloWorldJobConfig.class}) static class BatchTestConfig { @Autowired private Job helloWorlJob; @Bean JobLauncherTestUtils jobLauncherTestUtils() throws NoSuchJobException { JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils(); jobLauncherTestUtils.setJob(helloWorlJob); return jobLauncherTestUtils; } } }
要觸發上述測試用例,請在項目根文件夾中打開命令提示符,并執行以下Maven
命令:
mvn test
結果是構建成功,并在此期間執行批處理作業。
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.5.RELEASE) 2019-05-30 19:11:12.784 INFO 14588 --- [ main] c.c.SpringBatchApplicationTests : Starting SpringBatchApplicationTests on DESKTOP-2RB3C1U with PID 14588 (started by Codenotfound in C:\Users\Codenotfound\repos\spring-batch\spring-batch-hello-world) 2019-05-30 19:11:12.785 INFO 14588 --- [ main] c.c.SpringBatchApplicationTests : No active profile set, falling back to default profiles: default 2019-05-30 19:11:13.305 WARN 14588 --- [ main] o.s.b.c.c.a.DefaultBatchConfigurer : No datasource was provided...using a Map based JobRepository 2019-05-30 19:11:13.306 WARN 14588 --- [ main] o.s.b.c.c.a.DefaultBatchConfigurer : No transaction manager was provided, using a ResourcelessTransactionManager 2019-05-30 19:11:13.328 INFO 14588 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : No TaskExecutor has been set, defaulting to synchronous executor. 2019-05-30 19:11:13.350 INFO 14588 --- [ main] c.c.SpringBatchApplicationTests : Started SpringBatchApplicationTests in 0.894 seconds (JVM running for 1.777) 2019-05-30 19:11:13.732 INFO 14588 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=helloWorldJob]] launched with the following parameters: [{random=459672}] 2019-05-30 19:11:13.759 INFO 14588 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [helloWorldStep] 2019-05-30 19:11:13.812 INFO 14588 --- [ main] c.c.batch.PersonItemProcessor : converting 'John Doe' into 'Hello John Doe!' 2019-05-30 19:11:13.822 INFO 14588 --- [ main] c.c.batch.PersonItemProcessor : converting 'Jane Doe' into 'Hello Jane Doe!' 2019-05-30 19:11:13.842 INFO 14588 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=helloWorldJob]] completed with the following parameters: [{random=459672}] and the following status: [COMPLETED] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.953 s - in com.codenotfound.SpringBatchApplicationTests [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.852 s [INFO] Finished at: 2019-05-30T19:11:14+02:00 [INFO] ------------------------------------------------------------------------
您可以在target/test-output /greeting .txt
文件中找到結果:
Hello John Doe!
Hello Jane Doe!
如果您想運行上面的代碼示例,您可以在這里獲得完整的源代碼。
到此,關于“Spring Batch 的原理和作用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。