├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── github
│ │ └── dylanz666
│ │ ├── App.java
│ │ ├── config
│ │ ├── BatchConfig.java
│ │ └── SpringScheduledConfig.java
│ │ ├── controller
│ │ └── BatchController.java
│ │ └── service
│ │ ├── ItemProcessorService.java
│ │ ├── ItemProcessorService2.java
│ │ ├── ItemReaderService.java
│ │ ├── ItemReaderService2.java
│ │ ├── ItemWriterService.java
│ │ └── JobListener.java
└── resources
│ ├── application.properties
│ └── logback-spring.xml
└── test
└── java
└── com
└── github
└── dylanz666
└── AppTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # spring-batch-demo
2 | spring-batch-demo
3 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.github.dylanz666
5 | spring-boot-batch-demo
6 | jar
7 | 1.0-SNAPSHOT
8 | spring-boot-batch-demo
9 | https://github.com/dylanz666
10 |
11 |
12 | org.springframework.boot
13 | spring-boot-starter-parent
14 | 2.3.1.RELEASE
15 |
16 |
17 |
18 |
19 |
20 | alimaven
21 | aliyun maven
22 | http://maven.aliyun.com/nexus/content/repositories/central/
23 |
24 |
25 |
26 |
27 |
28 | junit
29 | junit
30 | 3.8.1
31 | test
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-web
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-batch
40 |
41 |
42 | com.h2database
43 | h2
44 | runtime
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-test
49 |
50 |
51 | org.projectlombok
52 | lombok
53 | 1.18.12
54 | provided
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/App.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666;
2 |
3 | import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | /**
8 | * @author : dylanz
9 | * @since : 08/25/2020
10 | */
11 | @SpringBootApplication
12 | @EnableBatchProcessing
13 | //@EnableScheduling
14 | public class App {
15 | public static void main(String[] args) {
16 | SpringApplication.run(App.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/config/BatchConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.config;
2 |
3 | import com.github.dylanz666.service.*;
4 | import org.springframework.batch.core.Job;
5 | import org.springframework.batch.core.JobExecutionListener;
6 | import org.springframework.batch.core.Step;
7 | import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
8 | import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
9 | import org.springframework.batch.core.launch.support.RunIdIncrementer;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.context.annotation.Configuration;
13 |
14 | /**
15 | * @author : dylanz
16 | * @since : 08/25/2020
17 | */
18 | @Configuration
19 | public class BatchConfig {
20 | @Autowired
21 | private JobBuilderFactory jobBuilderFactory;
22 | @Autowired
23 | private StepBuilderFactory stepBuilderFactory;
24 | @Autowired
25 | private ItemReaderService itemReaderService;
26 | @Autowired
27 | private ItemReaderService2 itemReaderService2;
28 | @Autowired
29 | private ItemProcessorService itemProcessorService;
30 | @Autowired
31 | private ItemProcessorService2 itemProcessorService2;
32 | @Autowired
33 | private ItemWriterService itemWriterService;
34 | @Autowired
35 | private JobListener jobListener;
36 |
37 | @Bean
38 | public Job singleStepJob() {
39 | return jobBuilderFactory.get("singleStepJob")
40 | .incrementer(new RunIdIncrementer())
41 | .listener(listener())
42 | .start(uppercaseStep())
43 | .build();
44 | }
45 |
46 | @Bean
47 | public Job multiBoundStepsJob() {
48 | return jobBuilderFactory.get("multiBoundStepsJob")
49 | .incrementer(new RunIdIncrementer())
50 | .listener(listener())
51 | .start(uppercaseStep())
52 | .next(addMessageStep())
53 | .build();
54 | }
55 |
56 | @Bean
57 | public Step uppercaseStep() {
58 | return stepBuilderFactory.get("uppercaseStep")
59 | .chunk(1)
60 | .reader(itemReaderService)
61 | .processor(itemProcessorService)
62 | .writer(itemWriterService).build();
63 | }
64 |
65 | @Bean
66 | public Step addMessageStep() {
67 | return stepBuilderFactory.get("addMessageStep")
68 | .chunk(1)
69 | .reader(itemReaderService2)
70 | .processor(itemProcessorService2)
71 | .writer(itemWriterService).build();
72 | }
73 |
74 | @Bean
75 | public JobExecutionListener listener() {
76 | return jobListener;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/config/SpringScheduledConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.config;
2 |
3 | import org.springframework.batch.core.Job;
4 | import org.springframework.batch.core.JobParameters;
5 | import org.springframework.batch.core.JobParametersBuilder;
6 | import org.springframework.batch.core.launch.JobLauncher;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.scheduling.annotation.Scheduled;
9 | import org.springframework.stereotype.Component;
10 |
11 | /**
12 | * @author : dylanz
13 | * @since : 08/25/2020
14 | */
15 | @Component
16 | public class SpringScheduledConfig {
17 | @Autowired
18 | private Job singleStepJob;
19 | @Autowired
20 | private JobLauncher jobLauncher;
21 |
22 | @Scheduled(cron = "0/5 * * * * ?")
23 | public void demoScheduled() throws Exception {
24 | JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
25 | .toJobParameters();
26 | jobLauncher.run(singleStepJob, jobParameters);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/controller/BatchController.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.controller;
2 |
3 | import org.springframework.batch.core.Job;
4 | import org.springframework.batch.core.JobParameters;
5 | import org.springframework.batch.core.JobParametersBuilder;
6 | import org.springframework.batch.core.launch.JobLauncher;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | /**
12 | * @author : dylanz
13 | * @since : 08/25/2020
14 | */
15 | @RestController
16 | public class BatchController {
17 | @Autowired
18 | private Job singleStepJob;
19 | @Autowired
20 | private Job multiBoundStepsJob;
21 | @Autowired
22 | private JobLauncher jobLauncher;
23 |
24 | @GetMapping("/job/step")
25 | public String invokeStep() throws Exception {
26 | JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
27 | .toJobParameters();
28 | jobLauncher.run(singleStepJob, jobParameters);
29 | return "The job is proceed.";
30 | }
31 |
32 | @GetMapping("/job/steps")
33 | public String invokeSteps() throws Exception {
34 | JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
35 | .toJobParameters();
36 | jobLauncher.run(multiBoundStepsJob, jobParameters);
37 | return "The multi bound steps job is proceed.";
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/ItemProcessorService.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.springframework.batch.item.ItemProcessor;
4 | import org.springframework.stereotype.Service;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * @author : dylanz
11 | * @since : 08/25/2020
12 | */
13 | @Service
14 | public class ItemProcessorService implements ItemProcessor {
15 | public static String[] message;
16 | //在此处进行数据处理操作,如进行计算、逻辑处理、格式转换等,本例将数据变成全大写数据;
17 | public String process(String data) throws Exception {
18 | //存储处理过的数据,可供下一个step使用
19 | List list = new ArrayList<>();
20 | if (message != null) {
21 | for (int i = 0; i < message.length; i++) {
22 | list.add(message[i]);
23 | }
24 | }
25 | list.add(data.toUpperCase());
26 | message = list.toArray(new String[list.size()]);
27 | return data.toUpperCase();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/ItemProcessorService2.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.springframework.batch.item.ItemProcessor;
4 | import org.springframework.stereotype.Service;
5 |
6 | /**
7 | * @author : dylanz
8 | * @since : 08/26/2020
9 | */
10 | @Service
11 | public class ItemProcessorService2 implements ItemProcessor {
12 | public String process(String data) throws Exception {
13 | return data + " dylanz";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/ItemReaderService.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.springframework.batch.item.ItemReader;
4 | import org.springframework.stereotype.Service;
5 |
6 | /**
7 | * @author : dylanz
8 | * @since : 08/25/2020
9 | */
10 | @Service
11 | public class ItemReaderService implements ItemReader {
12 | //在此处进行数据读取操作,如从数据库查询、从文件中读取、从变量中读取等,本例从变量中读取;
13 | private String[] message = {"message 1", "message 2", "message 3", "message 4", "message 5"};
14 | private int count = 0;
15 |
16 | public String read() throws Exception {
17 | if (count < message.length) {
18 | return message[count++];
19 | }
20 | count = 0;
21 | return null;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/ItemReaderService2.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.springframework.batch.item.ItemReader;
4 | import org.springframework.stereotype.Service;
5 |
6 | /**
7 | * @author : dylanz
8 | * @since : 08/26/2020
9 | */
10 | @Service
11 | public class ItemReaderService2 implements ItemReader {
12 | private int count = 0;
13 |
14 | public String read() throws Exception {
15 | if (ItemProcessorService.message != null && count < ItemProcessorService.message.length) {
16 | return ItemProcessorService.message[count++];
17 | }
18 | count = 0;
19 | return null;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/ItemWriterService.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.batch.item.ItemWriter;
6 | import org.springframework.stereotype.Service;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * @author : dylanz
12 | * @since : 08/25/2020
13 | */
14 | @Service
15 | public class ItemWriterService implements ItemWriter {
16 | private Logger logger = LoggerFactory.getLogger(this.getClass());
17 |
18 | //在此处进行数据输出操作,如写入数据库、写入文件、打印log等,本例为打印log;
19 | public void write(List extends String> messages) throws Exception {
20 | for (String message : messages) {
21 | logger.info("Writing data: " + message);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/github/dylanz666/service/JobListener.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666.service;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.batch.core.BatchStatus;
6 | import org.springframework.batch.core.JobExecution;
7 | import org.springframework.batch.core.JobExecutionListener;
8 | import org.springframework.stereotype.Service;
9 |
10 | /**
11 | * @author : dylanz
12 | * @since : 08/25/2020
13 | */
14 | @Service
15 | public class JobListener implements JobExecutionListener {
16 | private Logger logger = LoggerFactory.getLogger(this.getClass());
17 |
18 | public void beforeJob(JobExecution jobExecution) {
19 | logger.info("JOB IS STARTED.");
20 | }
21 |
22 | public void afterJob(JobExecution jobExecution) {
23 | if (jobExecution.getStatus() == BatchStatus.FAILED) {
24 | logger.info("JOB IS EXECUTED FAILED.");
25 | return;
26 | }
27 | if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
28 | logger.info("JOB IS EXECUTED SUCCESSFULLY.");
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
2 | spring.batch.job.enabled=false
3 | spring.datasource.url=jdbc:h2:~/test
4 | spring.datasource.driverClassName=org.h2.Driver
5 | spring.datasource.username=sa
6 | spring.datasource.password=123456
7 | spring.h2.console.path=/h2-console
8 | spring.h2.console.enabled=true
--------------------------------------------------------------------------------
/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | logback
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | INFO
13 |
14 | true
15 |
16 |
22 | %red([%d{yyyy-MM-dd HH:mm:ss}]) %green([ %thread ]) %highlight([ %-5level ]) %boldMagenta([ %logger ]) - %cyan(%msg%n)
23 |
24 | GBK
25 |
26 |
27 |
32 |
33 |
34 |
35 |
36 | ${LOG_PATH}/current.log
37 |
38 |
39 | ${LOG_ARCHIVE}/app.%d.%i.log.gz
40 | 30
41 | 20GB
42 |
44 |
45 | 10MB
46 |
47 |
48 |
49 | [%d{yyyy-MM-dd HH:mm:ss}] [ %thread ] [ %-5level ] [ %logger ] - %msg%n
50 | GBK
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
62 |
--------------------------------------------------------------------------------
/src/test/java/com/github/dylanz666/AppTest.java:
--------------------------------------------------------------------------------
1 | package com.github.dylanz666;
2 |
3 | import junit.framework.Test;
4 | import junit.framework.TestCase;
5 | import junit.framework.TestSuite;
6 |
7 | /**
8 | * Unit test for simple App.
9 | */
10 | public class AppTest
11 | extends TestCase
12 | {
13 | /**
14 | * Create the test case
15 | *
16 | * @param testName name of the test case
17 | */
18 | public AppTest( String testName )
19 | {
20 | super( testName );
21 | }
22 |
23 | /**
24 | * @return the suite of tests being tested
25 | */
26 | public static Test suite()
27 | {
28 | return new TestSuite( AppTest.class );
29 | }
30 |
31 | /**
32 | * Rigourous Test :-)
33 | */
34 | public void testApp()
35 | {
36 | assertTrue( true );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------