寫在最前
1、爲方便開發,本程序所用框架爲springboot+mybatis,同時mybatis還集成了 generator 插件;如果對這些開發環境不熟悉,建議先查詢相關資料,搭建springboot+mybatis環境,再集成spring batch。
2、在配置job、step等spring batch 的bean時,用的是java config方式,如想用xml方式配置,可參考 之前的博客:https://blog.csdn.net/Chris___/article/details/103166094
3、源代碼github: https://github.com/Horven-Jane/springBatchDemo1,可用於快速驗證。
------------------------------------------------------------------------------------------------------------------------------------------------
Job Repository 用來存儲Job執行期的元數據,這裏的元數據是指Job Instance、Job Execution、Job Parameters、StepExecution、Execution Context等數據。
有關元數據的介紹,這裏暫不做詳細介紹,讀者暫時可以將它們理解爲spring batch運行時產生的一些中間數據。
有兩種Job Repository 的實現方式,一種是存放在內存中,這在之前的博客中介紹了(https://blog.csdn.net/Chris___/article/details/103166094);另一種則是將元數據存放在數據庫中。
本篇文章介紹第二種方式——DB Job Repository。
將元數據存放在數據庫的好處:可以隨時監控批處理Job的執行狀態,查看Job執行結果是成功還是失敗,並且使得在job失敗的情況下重啓Job成爲可能。
以下是詳細步驟。
一、初始化數據庫
初始化數據庫,是指要建立相應的數據庫表,以便存放元數據。spring batch已經提供了相應的建表、銷表語句。
在包spring-batch-core jar包下的 org.springframework.batch.core 目錄中,可以找到相應的sql文件,如下:
本示例所用的數據庫是Mysql,因此執行 schema-mysql.sql 中的語句,即可完成初始化。
如果想銷表,則執行 schema-drop-mysql.sql。
初始化數據庫後,可以看到有9張元數據表:
表對應的描述如下:
二、搭建springboot+mybatis 環境
本項目採用springboot+mybatsi作爲框架,並用了mybatis的generator功能。
項目的業務場景是:從文件中讀取出用戶的信用卡消費賬單,簡單處理後(因爲是示例,所以這裏的處理只是打印出一句話),將這些賬單寫入數據庫。
項目的整體結構如下:
關於springboot+mybatis的集成,這裏不多介紹,可以查看博客:https://blog.csdn.net/iku5200/article/details/82856621
以下是詳細步驟。
1、建立一個maven工程,引入springboot、mybatis 以及 spring batch的相關包,pom文件如下:
<?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.maple</groupId>
<artifactId>springBatchStudy02</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring boot 整合 spring batch 的jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- mybatis generator 自動生成代碼插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}\src\main\resources\generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、接着配置數據庫連接,編寫application.properties以及application-dev.properties文件。
application.properties 中只有一句話:
spring.profiles.active=dev
表示當前環境是dev。
application-dev.properties 內容如下:
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/spring_batch?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.mapper-locations=classpath:mapping/*.xml
#全局的映射,不用在xml文件寫實體類的全路徑
mybatis.type-aliases-package=com.maple.model
#開啓駝峯映射
mybatis.configuration.map-underscore-to-camel-case=true
所用的數據源是Druid。
3、編寫業務代碼
編寫業務實體類CreditBill,該類有5個字段,如下:
public class CreditBill implements Serializable {
private String accountId;
private String name;
private Double txnAmount;
private String txnDate;
private String address;
}
利用mybatis的 generator 生成相應的Mapper 文件,以方便操作數據庫。
4、配置作業(Java Config 方式 )
用Java Config 來配置 Job 以及Step。這是本文的重點。文件BatchConfig02.java內容如下:
@Configuration
@EnableBatchProcessing
public class BatchConfig02 {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public FlatFileItemReader<CreditBill> flatFileItemReader(){
FlatFileItemReader<CreditBill> reader = new FlatFileItemReader<>();
Resource resource = new FileSystemResource("src\\main\\resources\\data\\ch02\\credit_bill_info_02.txt");
reader.setResource(resource);
BeanWrapperFieldSetMapper fieldSetMapper = new BeanWrapperFieldSetMapper();
fieldSetMapper.setTargetType(CreditBill.class);
DefaultLineMapper<CreditBill> lineMapper = new DefaultLineMapper<>();
lineMapper.setFieldSetMapper(fieldSetMapper);
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setDelimiter(",");
tokenizer.setNames("accountId", "name", "txnAmount", "txnDate", "address");
lineMapper.setLineTokenizer(tokenizer);
reader.setLineMapper(lineMapper);
return reader;
}
@Bean
public CreditBillProcess02 creditBillProcess02(){
return new CreditBillProcess02();
}
@Bean
public ItemWriter<CreditBill> creditBillDBWritter02(){
return new CreditBillDBWritter02();
}
/**
* 將 creditBill 寫入數據庫
* @return
*/
@Bean
public Job creditBillPersistJob(){
return jobBuilderFactory.get("creditBillPersistJob")
.start(creditBillPersistStep())
.build();
}
@Bean
public Step creditBillPersistStep(){
return stepBuilderFactory.get("creditBillPersistStep")
.<CreditBill, CreditBill>chunk(2)
.reader(flatFileItemReader())
.processor(creditBillProcess02())
.writer(creditBillDBWritter02())
.build();
}
}
注意:
1、需要加上 @EnableBatchProcessing 註解,這個註解的解析,見博客:https://blog.csdn.net/Chris___/article/details/103352103 ;
2、作業 job 和步驟 step 的名字,是在方法名中定義的;
3、CreditBillProcess02 只是簡單地打印一句話,CreditBillDBWritter02 則把信用卡賬單數據寫入到mysql中。
三、運行
1、先造幾個信用卡賬單數據,放在credit_bill_info_02.txt 這個文件中,如下:
00000001,zhang1,3500,20190106,shenzhen
00000002,zhang2,300,20190106,shenzhen
00000003,zhang3,200,20190106,shenzhen
00000004,zhang4,500.2,20190106,shenzhen
00000005,zhang5,10,20190106,shenzhen
00000006,zhang6,600,20190106,shenzhen
2、編寫一個Springboot的啓動類,這個啓動類上需要用上註解@SpringBootApplication
另外,如果想多次運行同一個任務(任務名相同),則需要給該任務加上不同的參數。
啓動類如下:
//如果沒有MapperScan這個註解,則每個mapper接口上都必須加上@Mapper 註解
@MapperScan("com.maple.dao.mapper")
@SpringBootApplication
public class Bootstrap {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Bootstrap.class, args);
JobLauncher launcher = (JobLauncher)context.getBean("jobLauncher");
Job job1 = (Job)context.getBean("creditBillPersistJob");
try{
JobParametersBuilder paramBuilder = new JobParametersBuilder();
paramBuilder.addLong("DS", System.currentTimeMillis());
JobExecution jobExecution = launcher.run(job1, paramBuilder.toJobParameters());
System.out.println("JobExecution : " + jobExecution.toString());
} catch (Exception e){
e.printStackTrace();
}
}
}
在本示例中,我給每個任務加上一個DS的參數,該參數的值是時間戳,所以可多次運行同一個任務。
3、驗證結果
運行程序後,查看數據庫中是否正確寫入了信用卡賬單的信息。
四、源代碼
github : https://github.com/Horven-Jane/springBatchDemo1