Skip to content

Commit b7aa99b

Browse files
committed
Spring Batch异常处理
1 parent 643b7d8 commit b7aa99b

File tree

10 files changed

+395
-0
lines changed

10 files changed

+395
-0
lines changed

72.spring-batch-exception/pom.xml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>2.2.5.RELEASE</version>
9+
<relativePath/> <!-- lookup parent from repository -->
10+
</parent>
11+
<groupId>cc.mrbird</groupId>
12+
<artifactId>spring-batch-exception</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>spring-batch-exception</name>
15+
<description>Demo project for Spring Boot</description>
16+
17+
<properties>
18+
<java.version>1.8</java.version>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter-batch</artifactId>
25+
</dependency>
26+
27+
<dependency>
28+
<groupId>mysql</groupId>
29+
<artifactId>mysql-connector-java</artifactId>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.springframework.boot</groupId>
33+
<artifactId>spring-boot-starter-jdbc</artifactId>
34+
</dependency>
35+
</dependencies>
36+
37+
<build>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.springframework.boot</groupId>
41+
<artifactId>spring-boot-maven-plugin</artifactId>
42+
</plugin>
43+
</plugins>
44+
</build>
45+
46+
</project>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package cc.mrbird.batch;
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+
@SpringBootApplication
8+
@EnableBatchProcessing
9+
public class SpringBatchExceptionApplication {
10+
11+
public static void main(String[] args) {
12+
SpringApplication.run(SpringBatchExceptionApplication.class, args);
13+
}
14+
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package cc.mrbird.batch.exception;
2+
3+
/**
4+
* @author MrBird
5+
*/
6+
public class MyJobExecutionException extends Exception{
7+
8+
private static final long serialVersionUID = 7168487913507656106L;
9+
10+
public MyJobExecutionException(String message) {
11+
super(message);
12+
}
13+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package cc.mrbird.batch.job;
2+
3+
import org.springframework.batch.core.Job;
4+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
5+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
6+
import org.springframework.batch.item.ExecutionContext;
7+
import org.springframework.batch.repeat.RepeatStatus;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.stereotype.Component;
11+
12+
/**
13+
* @author MrBird
14+
*/
15+
@Component
16+
public class DefaultExceptionJobDemo {
17+
18+
@Autowired
19+
private JobBuilderFactory jobBuilderFactory;
20+
@Autowired
21+
private StepBuilderFactory stepBuilderFactory;
22+
23+
@Bean
24+
public Job defaultExceptionJob() {
25+
return jobBuilderFactory.get("defaultExceptionJob")
26+
.start(
27+
stepBuilderFactory.get("step")
28+
.tasklet((stepContribution, chunkContext) -> {
29+
// 获取执行上下文
30+
ExecutionContext executionContext = chunkContext.getStepContext().getStepExecution().getExecutionContext();
31+
if (executionContext.containsKey("success")) {
32+
System.out.println("任务执行成功");
33+
return RepeatStatus.FINISHED;
34+
} else {
35+
String errorMessage = "处理任务过程发生异常";
36+
System.out.println(errorMessage);
37+
executionContext.put("success", true);
38+
throw new RuntimeException(errorMessage);
39+
}
40+
41+
}).build()
42+
).build();
43+
}
44+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package cc.mrbird.batch.job;
2+
3+
import org.springframework.batch.core.Job;
4+
import org.springframework.batch.core.Step;
5+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
6+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
7+
import org.springframework.batch.item.support.ListItemReader;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.stereotype.Component;
11+
import org.springframework.transaction.annotation.Isolation;
12+
import org.springframework.transaction.annotation.Propagation;
13+
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
14+
15+
import java.util.ArrayList;
16+
import java.util.stream.IntStream;
17+
18+
/**
19+
* @author MrBird
20+
*/
21+
@Component
22+
public class RestartJobDemo {
23+
24+
@Autowired
25+
private JobBuilderFactory jobBuilderFactory;
26+
@Autowired
27+
private StepBuilderFactory stepBuilderFactory;
28+
29+
@Bean
30+
public Job restartJob() {
31+
return jobBuilderFactory.get("restartJob")
32+
.start(step())
33+
.build();
34+
}
35+
36+
private Step step() {
37+
return stepBuilderFactory.get("step")
38+
.<String, String>chunk(2)
39+
.reader(listItemReader())
40+
.writer(list -> list.forEach(System.out::println))
41+
// .allowStartIfComplete(true)
42+
.startLimit(1)
43+
.build();
44+
}
45+
46+
private ListItemReader<String> listItemReader() {
47+
ArrayList<String> datas = new ArrayList<>();
48+
IntStream.range(0, 5).forEach(i -> datas.add(String.valueOf(i)));
49+
return new ListItemReader<>(datas);
50+
}
51+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package cc.mrbird.batch.job;
2+
3+
import cc.mrbird.batch.exception.MyJobExecutionException;
4+
import org.springframework.batch.core.Job;
5+
import org.springframework.batch.core.Step;
6+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
7+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
8+
import org.springframework.batch.item.ItemProcessor;
9+
import org.springframework.batch.item.support.ListItemReader;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.stereotype.Component;
13+
14+
import java.util.ArrayList;
15+
import java.util.stream.IntStream;
16+
17+
/**
18+
* @author MrBird
19+
*/
20+
@Component
21+
public class RetryExceptionJobDemo {
22+
23+
@Autowired
24+
private JobBuilderFactory jobBuilderFactory;
25+
@Autowired
26+
private StepBuilderFactory stepBuilderFactory;
27+
28+
@Bean
29+
public Job retryExceptionJob() {
30+
return jobBuilderFactory.get("retryExceptionJob")
31+
.start(step())
32+
.build();
33+
}
34+
35+
private Step step() {
36+
return stepBuilderFactory.get("step")
37+
.<String, String>chunk(2)
38+
.reader(listItemReader())
39+
.processor(myProcessor())
40+
.writer(list -> list.forEach(System.out::println))
41+
.faultTolerant() // 配置错误容忍
42+
.retry(MyJobExecutionException.class) // 配置重试的异常类型
43+
.retryLimit(3) // 重试3次,三次过后还是异常的话,则任务会结束,
44+
// 异常的次数为reader,processor和writer中的总数,这里仅在processor里演示异常重试
45+
.build();
46+
}
47+
48+
private ListItemReader<String> listItemReader() {
49+
ArrayList<String> datas = new ArrayList<>();
50+
IntStream.range(0, 5).forEach(i -> datas.add(String.valueOf(i)));
51+
return new ListItemReader<>(datas);
52+
}
53+
54+
private ItemProcessor<String, String> myProcessor() {
55+
return new ItemProcessor<String, String>() {
56+
private int count;
57+
@Override
58+
public String process(String item) throws Exception {
59+
System.out.println("当前处理的数据:" + item);
60+
if (count >= 2) {
61+
return item;
62+
} else {
63+
count++;
64+
throw new MyJobExecutionException("任务处理出错");
65+
}
66+
}
67+
};
68+
}
69+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package cc.mrbird.batch.job;
2+
3+
import cc.mrbird.batch.exception.MyJobExecutionException;
4+
import cc.mrbird.batch.listener.MySkipListener;
5+
import org.springframework.batch.core.Job;
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.item.ItemProcessor;
10+
import org.springframework.batch.item.support.ListItemReader;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.context.annotation.Bean;
13+
import org.springframework.stereotype.Component;
14+
15+
import java.util.ArrayList;
16+
import java.util.stream.IntStream;
17+
18+
/**
19+
* @author MrBird
20+
*/
21+
@Component
22+
public class SkipExceptionJobDemo {
23+
24+
@Autowired
25+
private JobBuilderFactory jobBuilderFactory;
26+
@Autowired
27+
private StepBuilderFactory stepBuilderFactory;
28+
@Autowired
29+
private MySkipListener mySkipListener;
30+
31+
@Bean
32+
public Job skipExceptionJob() {
33+
return jobBuilderFactory.get("skipExceptionJob")
34+
.start(step())
35+
.build();
36+
}
37+
38+
private Step step() {
39+
return stepBuilderFactory.get("step")
40+
.<String, String>chunk(2)
41+
.reader(listItemReader())
42+
.processor(myProcessor())
43+
.writer(list -> list.forEach(System.out::println))
44+
.faultTolerant() // 配置错误容忍
45+
.skip(MyJobExecutionException.class) // 配置跳过的异常类型
46+
.skipLimit(1) // 最多跳过1次,1次过后还是异常的话,则任务会结束,
47+
// 异常的次数为reader,processor和writer中的总数,这里仅在processor里演示异常跳过
48+
.listener(mySkipListener)
49+
.build();
50+
}
51+
52+
private ListItemReader<String> listItemReader() {
53+
ArrayList<String> datas = new ArrayList<>();
54+
IntStream.range(0, 5).forEach(i -> datas.add(String.valueOf(i)));
55+
return new ListItemReader<>(datas);
56+
}
57+
58+
private ItemProcessor<String, String> myProcessor() {
59+
return item -> {
60+
System.out.println("当前处理的数据:" + item);
61+
if ("2".equals(item)) {
62+
throw new MyJobExecutionException("任务处理出错");
63+
} else {
64+
return item;
65+
}
66+
};
67+
}
68+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package cc.mrbird.batch.job;
2+
3+
import cc.mrbird.batch.exception.MyJobExecutionException;
4+
import org.springframework.batch.core.Job;
5+
import org.springframework.batch.core.Step;
6+
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
7+
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
8+
import org.springframework.batch.item.ItemProcessor;
9+
import org.springframework.batch.item.support.ListItemReader;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.stereotype.Component;
13+
import org.springframework.transaction.annotation.Isolation;
14+
import org.springframework.transaction.annotation.Propagation;
15+
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
16+
17+
import java.util.ArrayList;
18+
import java.util.stream.IntStream;
19+
20+
/**
21+
* @author MrBird
22+
*/
23+
@Component
24+
public class TransactionJobDemo {
25+
26+
@Autowired
27+
private JobBuilderFactory jobBuilderFactory;
28+
@Autowired
29+
private StepBuilderFactory stepBuilderFactory;
30+
31+
@Bean
32+
public Job transactionJob() {
33+
return jobBuilderFactory.get("transactionJob")
34+
.start(step())
35+
.build();
36+
}
37+
38+
private Step step() {
39+
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
40+
attribute.setPropagationBehavior(Propagation.REQUIRED.value());
41+
attribute.setIsolationLevel(Isolation.DEFAULT.value());
42+
attribute.setTimeout(30);
43+
44+
return stepBuilderFactory.get("step")
45+
.<String, String>chunk(2)
46+
.reader(listItemReader())
47+
.writer(list -> list.forEach(System.out::println))
48+
.readerIsTransactionalQueue()
49+
.transactionAttribute(attribute)
50+
.build();
51+
}
52+
53+
private ListItemReader<String> listItemReader() {
54+
ArrayList<String> datas = new ArrayList<>();
55+
IntStream.range(0, 5).forEach(i -> datas.add(String.valueOf(i)));
56+
return new ListItemReader<>(datas);
57+
}
58+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package cc.mrbird.batch.listener;
2+
3+
import org.springframework.batch.core.SkipListener;
4+
import org.springframework.stereotype.Component;
5+
6+
/**
7+
* @author MrBird
8+
*/
9+
@Component
10+
public class MySkipListener implements SkipListener<String, String> {
11+
@Override
12+
public void onSkipInRead(Throwable t) {
13+
System.out.println("在读取数据的时候遇到异常并跳过,异常:" + t.getMessage());
14+
}
15+
16+
@Override
17+
public void onSkipInWrite(String item, Throwable t) {
18+
System.out.println("在输出数据的时候遇到异常并跳过,待输出数据:" + item + ",异常:" + t.getMessage());
19+
}
20+
21+
@Override
22+
public void onSkipInProcess(String item, Throwable t) {
23+
System.out.println("在处理数据的时候遇到异常并跳过,待输出数据:" + item + ",异常:" + t.getMessage());
24+
}
25+
}

0 commit comments

Comments
 (0)