基於Spring Batch的Spring Boot的教程 - Baeldung
在本文中,我們將學習如何使用Spring Boot建立一個簡單的Spring Batch作業。首先,我們從定義一些基本配置開始。然後,我們將看到如何新增檔案讀取器和資料庫寫入器。最後,如何應用一些自定義處理並檢查我們的作業是否成功執行。
可以在GitHub上獲得本文的完整原始碼 。
首先,讓我們將spring-boot-starter-batch新增到我們的 pom.xml中:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> <version>2.4.0.RELEASE</version> </dependency> |
我們還將新增org.hsqldb依賴關係,該依賴關係也可以從Maven Central 獲得:
<dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.5.1</version> <scope>runtime</scope> </dependency> |
我們將構建一個工作,該工作將從CSV檔案匯入咖啡清單,使用自定義處理器對其進行轉換,然後將最終結果儲存在記憶體資料庫中。
讓我們從定義應用程式入口點開始:
@SpringBootApplication public class SpringBootBatchProcessingApplication { public static void main(String[] args) { SpringApplication.run(SpringBootBatchProcessingApplication.class, args); } } |
如我們所見,這是一個標準的Spring Boot應用程式。由於我們希望在可能的情況下使用預設配置值,因此我們將使用一組非常簡單的應用程式配置屬性。
我們將在src / main / resources / application.properties檔案中定義以下屬性:
file.input=coffee-list.csv |
此屬性包含我們輸入的咖啡清單的位置。每行都包含我們咖啡的品牌,來源和一些特徵:
Blue Mountain,Jamaica,Fruity Lavazza,Colombia,Strong Folgers,America,Smokey |
我們將看到,這是一個平面CSV檔案,這意味著Spring可以在不進行任何特殊自定義的情況下對其進行處理。
接下來,我們將新增一個SQL指令碼schema-all.sql來建立我們的咖啡桌來儲存資料:
DROP TABLE coffee IF EXISTS; CREATE TABLE coffee ( coffee_id BIGINT IDENTITY NOT NULL PRIMARY KEY, brand VARCHAR(20), origin VARCHAR(20), characteristics VARCHAR(30) ); |
通常,Spring Boot將在啟動過程中自動執行此指令碼。
隨後,我們將需要一個簡單的域類來儲存我們的咖啡專案:
public class Coffee { private String brand; private String origin; private String characteristics; public Coffee(String brand, String origin, String characteristics) { this.brand = brand; this.origin = origin; this.characteristics = characteristics; } // getters and setters } |
如前所述,我們的Coffee物件包含三個屬性。
現在,到關鍵部分,我們的工作配置。我們將逐步進行,建立我們的配置並解釋其中的每個部分:
@Configuration @EnableBatchProcessing public class BatchConfiguration { @Autowired public JobBuilderFactory jobBuilderFactory; @Autowired public StepBuilderFactory stepBuilderFactory; @Value("${file.input}") private String fileInput; // ... } |
首先,我們從標準的Spring @Configuration類開始。接下來,我們在類中新增 @EnableBatchProcessing批註。值得注意的是,這使我們能夠使用許多有用的bean來支援工作,並將節省大量的日常工作。
此外,使用此註釋還使我們可以訪問兩個有用的工廠,稍後將在構建作業配置和作業步驟時使用它們。
對於初始配置的最後一部分,我們包括對先前宣告的file.input屬性的引用。
現在,我們可以繼續在配置中定義一個閱讀器bean:
@Bean public FlatFileItemReader reader() { return new FlatFileItemReaderBuilder().name("coffeeItemReader") .resource(new ClassPathResource(fileInput)) .delimited() .names(new String[] { "brand", "origin", "characteristics" }) .fieldSetMapper(new BeanWrapperFieldSetMapper() {{ setTargetType(Coffee.class); }}) .build(); } |
簡而言之,上面定義的閱讀器bean將查詢名為coffee-list.csv的檔案,並將每個訂單項解析為Coffee物件。
同樣,我們定義一個writer bean:
@Bean public JdbcBatchItemWriter writer(DataSource dataSource) { return new JdbcBatchItemWriterBuilder() .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) .sql("INSERT INTO coffee (brand, origin, characteristics) VALUES (:brand, :origin, :characteristics)") .dataSource(dataSource) .build(); } |
這次,我們包含了由咖啡物件的Java Bean屬性驅動的將單個咖啡專案插入到資料庫中所需的SQL語句。方便地,透過@EnableBatchProcessing批註自動建立dataSource。
最後,我們需要新增實際的作業步驟和配置:
@Bean public Job importUserJob(JobCompletionNotificationListener listener, Step step1) { return jobBuilderFactory.get("importUserJob") .incrementer(new RunIdIncrementer()) .listener(listener) .flow(step1) .end() .build(); } @Bean public Step step1(JdbcBatchItemWriter writer) { return stepBuilderFactory.get("step1") .<Coffee, Coffee> chunk(10) .reader(reader()) .processor(processor()) .writer(writer) .build(); } @Bean public CoffeeItemProcessor processor() { return new CoffeeItemProcessor(); } |
如我們所見,我們的工作相對簡單,由step1方法中定義的一個步驟組成。
讓我們看一下此步驟正在執行的操作:
- 首先,我們配置步驟,以便使用chunk(10)宣告一次最多寫入十條記錄
- 然後,我們使用讀取器bean讀取咖啡資料,該讀取器bean是使用reader方法設定的
- 接下來,我們將每個咖啡專案傳遞給自定義處理器,在其中應用一些自定義業務邏輯
- 最後,我們使用之前看到的編寫器將每個咖啡專案寫入資料庫
另一方面,我們的importUserJob包含我們的作業定義,其中包含使用內建RunIdIncrementer類的ID 。我們還設定了一個JobCompletionNotificationListener,用來在作業完成時得到通知。
為了完成我們的作業配置,我們列出了每個步驟(儘管此作業只有一個步驟)。現在,我們已經完成了完美的配置!
讓我們詳細瞭解一下我們先前在作業配置中定義的自定義處理器:
public class CoffeeItemProcessor implements ItemProcessor<Coffee, Coffee> { private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class); @Override public Coffee process(final Coffee coffee) throws Exception { String brand = coffee.getBrand().toUpperCase(); String origin = coffee.getOrigin().toUpperCase(); String chracteristics = coffee.getCharacteristics().toUpperCase(); Coffee transformedCoffee = new Coffee(brand, origin, chracteristics); LOGGER.info("Converting ( {} ) into ( {} )", coffee, transformedCoffee); return transformedCoffee; } } |
特別感興趣的是,ItemProcessor介面為我們提供了一種在作業執行期間應用某些特定業務邏輯的機制。
為了簡單起見,我們定義了CoffeeItemProcessor,它接受一個輸入Coffee物件,並將每個屬性轉換為uppercase。
此外,我們還將編寫一個JobCompletionNotificationListener, 以在工作完成時提供一些反饋:
@Override public void afterJob(JobExecution jobExecution) { if (jobExecution.getStatus() == BatchStatus.COMPLETED) { LOGGER.info("!!! JOB FINISHED! Time to verify the results"); String query = "SELECT brand, origin, characteristics FROM coffee"; jdbcTemplate.query(query, (rs, row) -> new Coffee(rs.getString(1), rs.getString(2), rs.getString(3))) .forEach(coffee -> LOGGER.info("Found < {} > in the database.", coffee)); } } |
在上面的示例中,我們重寫afterJob方法並檢查作業是否成功完成。此外,我們執行一個簡單查詢以檢查每個咖啡專案是否已成功儲存在資料庫中。
現在我們已經準備就緒,可以開始工作了,這是有趣的部分。讓我們繼續工作吧:
... 17:41:16.336 [main] INFO c.b.b.JobCompletionNotificationListener - !!! JOB FINISHED! Time to verify the results 17:41:16.336 [main] INFO c.b.b.JobCompletionNotificationListener - Found < Coffee [brand=BLUE MOUNTAIN, origin=JAMAICA, characteristics=FRUITY] > in the database. 17:41:16.337 [main] INFO c.b.b.JobCompletionNotificationListener - Found < Coffee [brand=LAVAZZA, origin=COLOMBIA, characteristics=STRONG] > in the database. 17:41:16.337 [main] INFO c.b.b.JobCompletionNotificationListener - Found < Coffee [brand=FOLGERS, origin=AMERICA, characteristics=SMOKEY] > in the database. ... |
如我們所見,我們的工作成功執行,每項咖啡都按預期儲存在資料庫中。
相關文章
- Spring Boot整合Spring BatchSpring BootBAT
- Spring Boot的Clean架構教程與原始碼 - BaeldungSpring Boot架構原始碼
- 使用Spring Boot排程WebSocket推送的教程和原始碼 - BaeldungSpring BootWeb原始碼
- Spring Boot Reactor Netty配置 | BaeldungSpring BootReactNetty
- 在Spring Batch中配置重試邏輯 - BaeldungSpringBAT
- Spring Boot面試問題| BaeldungSpring Boot面試
- 加快Spring Boot啟動的幾種方法 | baeldungSpring Boot
- Spring Boot 之 Spring Batch 批處理實踐Spring BootBAT
- spring boot基於Java的容器配置Spring BootJava
- 在Spring Boot設定Swagger 2 - BaeldungSpring BootSwagger
- GraphQL SPQR和Spring Boot入門 | baeldungSpring Boot
- Spring Boot基礎教程:EhCache快取的使用Spring Boot快取
- 基於Spring Boot傳送 mailSpring BootAI
- Spring Boot專案的推薦軟體包結構 - BaeldungSpring Boot
- 基於spring-boot&spring-data-jpa的web開發環境整合SpringbootWeb開發環境
- Spring Boot 教程 - ElasticsearchSpring BootElasticsearch
- Spring Boot2 系列教程(三)理解 Spring BootSpring Boot
- 陪你解讀Spring Batch(一)Spring Batch介紹SpringBAT
- Wizzdi :基於 Spring Boot 的無程式碼系統Spring Boot
- 關於使用Spring Boot的Kafka教程 - DZone大資料Spring BootKafka大資料
- Spring Boot微服務中的十二因子方法論(12Factor) - BaeldungSpring Boot微服務
- 基於Istio/gRPC/Redis/BigQuery/Spring Boot/Spring Cloud和Stackdriver的微服務案例RPCRedisSpring BootCloud微服務
- 陪你解讀Spring Batch(二)帶你入手Spring BatchSpringBAT
- Spring Boot Test 的詳細使用教程Spring Boot
- Spring boot學習(二) Spring boot基礎配置Spring Boot
- Spring Batch + JPA 處理 Excel 檔案教程SpringBATExcel
- Spring Boot 基礎Spring Boot
- Idea下構建基於Gradle的Spring Boot專案IdeaGradleSpring Boot
- guns Lite基於spring boot的後臺管理系統Spring Boot
- Spring Boot 基於 SCRAM 認證整合 Kafka 的詳解Spring BootKafka
- 基於 Spring Boot 的個人部落格 FS-BlogSpring Boot
- Spring Boot-Redis教程Spring BootRedis
- Spring Boot Security配置教程Spring Boot
- 基於Spring Boot和Spring Cloud實現微服務架構Spring BootCloud微服務架構
- Spring / Spring boot 基於註解非同步程式設計@AsyncSpring Boot非同步程式設計
- Spring Boot 2.x基礎教程:Spring Data JPA的多資料來源配置Spring Boot
- Spring Boot 2.x基礎教程:EhCache快取的使用Spring Boot快取
- 結合GraalVM與Spring Native的Spring Boot原始碼教程 | foojayLVMSpring Boot原始碼