直接上代码
■ 共通部分:
1. 代码结构

 
2. pom.xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency> 
3. framework/BatchAnnotation.java
package roy.springbatch.framework;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@Import({SimpleBatchConfiguration.class})
@EnableBatchProcessing
@ComponentScan
@ComponentScans({@ComponentScan("roy.springbatch.framework")})
@PropertySource(value = "classpath:config/jdbc-dev.properties")
public @interface BatchAnnotation {
}
 
4. framework/BaseModule.java
package roy.springbatch.framework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import java.util.HashMap;
import java.util.Map;
public abstract class BaseModule implements CommandLineRunner {
    private static final Logger log = LoggerFactory.getLogger(BaseModule.class);
    public static void run(Class<? extends BaseModule> module, String batchName, String[] args)
        throws Exception {
        SpringApplication app = new SpringApplication(module);
        Map<String, Object> param = retriveArgs(batchName, args);
        app.setDefaultProperties(param);
        app.run(args);
    }
    private static Map<String, Object> retriveArgs(String batchName, String[] args){
        Map<String, Object> param = new HashMap<>();
        param.put("argsLength", args.length);
        if (args.length>0){
            param.put("targetDate", args[0]);
        }
        return param;
    }
    @Override
    public void run(String... args) throws Exception{
        if (null != args){
            for(String arg : args){
                log.info("execute module with argument : " + arg);
            }
        }
    }
}
 
5. framework/BaseWriter.java
package roy.springbatch.framework;
import org.springframework.batch.core.JobParameter;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
public abstract class BaseWriter<T> implements ItemWriter<T> {
    protected StepExecution stepExecution;
    @BeforeStep
    public void saveStepExecution(StepExecution stepExecution){
        this.stepExecution = stepExecution;
    }
    @Override
    public void write(List<? extends T> items) throws Exception {
        JobParameters params = stepExecution.getJobParameters();
        ExecutionContext stepContext = stepExecution.getExecutionContext();
        for(T item : items){
            doWrite(item, params, stepContext);
        }
    }
    public abstract void doWrite(T item, JobParameters params, ExecutionContext stepContext) throws Exception;
}
 
一. Tasklet
1. batTasklet/BatTasklet.java
package roy.springbatch.batTasklet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import roy.springbatch.framework.BaseModule;
import roy.springbatch.framework.BatchAnnotation;
@BatchAnnotation
public class BatTasklet extends BaseModule {
    private static final Logger log = LoggerFactory.getLogger(BatTasklet.class);
    private static final String MODULE_NAME = "BATCHTASKLET";
    public static void main(String[] args) {
        try {
            run(BatTasklet.class, MODULE_NAME, args);
        } catch (Exception e) {
            log.error(MODULE_NAME + " failed.");
            System.exit(1);
        }
    }
}
 
2. batTasklet/BatTaskletConfiguration.java
package roy.springbatch.batTasklet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import roy.springbatch.framework.BaseModule;
@Configuration
@EnableBatchProcessing
public class BatTaskletConfiguration extends BaseModule {
    private static final Logger log = LoggerFactory.getLogger(BatTaskletConfiguration.class);
    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private Tasklet tasklet1;
    @Autowired
    private Tasklet tasklet2;
    @Bean
    public Step step1(){
        return stepBuilderFactory.get("step1")
                .allowStartIfComplete(true)
                .tasklet(tasklet1)
                .build();
    }
    @Bean
    public Step step2(){
        return stepBuilderFactory.get("step2")
                .allowStartIfComplete(true)
                .tasklet(tasklet2)
                .build();
    }
    @Bean
    public Job job(){
        return jobBuilderFactory.get("step-tasklet-job")
                .incrementer(new RunIdIncrementer())
                .start(step1())
                .next(step2())
                .build();
    }
}
 
3. batTasklet/Task1.java (具体想要做的事情写在Task里面)
package roy.springbatch.batTasklet;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class Task1 {
    @Bean
    public Tasklet tasklet1(){
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("--->Tasklet 1 Execute:" + System.currentTimeMillis());
                return RepeatStatus.FINISHED;
            }
        };
    }
}
 
4. batTasklet/Task2.java
package roy.springbatch.batTasklet;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class Task2 {
    @Bean
    public Tasklet tasklet2(){
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("--->Tasklet 2 Execute:" + System.currentTimeMillis());
                return RepeatStatus.FINISHED;
            }
        };
    }
}
 
5. 测试:

二. Chunk
1. batChunk/listener/BatChunkListener.java
package roy.springbatch.batChunk.listener;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.stereotype.Component;
@Component
public class BatChunkListener extends JobExecutionListenerSupport {
    @Override
    public void beforeJob(JobExecution jobExecution){
        System.out.println("--->BeforeJob Execute");
    }
    @Override
    public void afterJob(JobExecution jobExecution){
        System.out.println("--->AfterJob Execute");
    }
}
 
2. batChunk/reader/BatChunkReader.java
package roy.springbatch.batChunk.reader;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import java.util.HashMap;
import java.util.Map;
public class BatChunkReader implements ItemReader<Map<String, String>> {
    private int stepCount = 0;
    private Map<String, String> listMap = new HashMap<>();
    @Override
    public Map<String, String> read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if(stepCount<3){
            stepCount++;
            System.out.println("--->Reader Execute: read from DB");
            listMap.put("A1", "1");
            listMap.put("A2", "2");
            listMap.put("A3", "3");
            return listMap;
        }else {
            return null;
        }
    }
}
 
3. batChunk/writer/BatChunkWriter.java
package roy.springbatch.batChunk.writer;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import roy.springbatch.framework.BaseWriter;
import java.util.Map;
@Component
@Scope("prototype")
public class BatChunkWriter extends BaseWriter<Map<String, String>> {
    @Override
    public void doWrite(Map<String, String> map, JobParameters params,
                        ExecutionContext stepContext) throws Exception {
        System.out.println("--->Writer Execute: write to DB:" + map.toString());
    }
}
 
4. batChunk/BatChunk.java
package roy.springbatch.batChunk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import roy.springbatch.framework.BaseModule;
import roy.springbatch.framework.BatchAnnotation;
@BatchAnnotation
public class BatChunk extends BaseModule {
    private static final Logger log = LoggerFactory.getLogger(BatChunk.class);
    private static final String MODULE_NAME = "BATCHCHUNK";
    public static void main(String[] args) {
        try {
            run(BatChunk.class, MODULE_NAME, args);
        } catch (Exception e) {
            log.error(MODULE_NAME + " failed.");
            System.exit(1);
        }
    }
}
 
5. batChunk/BatChunkConfiguration.java
package roy.springbatch.batChunk;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.transaction.PlatformTransactionManager;
import roy.springbatch.batChunk.listener.BatChunkListener;
import roy.springbatch.batChunk.reader.BatChunkReader;
import roy.springbatch.batChunk.writer.BatChunkWriter;
import java.util.Map;
@Configuration
@EnableBatchProcessing
public class BatChunkConfiguration {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private BatChunkWriter batChunkWriter;
    @Autowired
    private PlatformTransactionManager dbWriteManager;
    @Bean
    @Scope("prototype")
    public ItemReader<Map<String, String>> readerByMyBatis() {
        return new BatChunkReader();
    }
    @Bean
    public Job insertJob(BatChunkListener listener){
        String jobName = "InsertJob:" + System.currentTimeMillis();
        return jobBuilderFactory.get(jobName).start(stepInsert()).listener(listener).build();
    }
    @Bean
    public Step stepInsert(){
        return stepBuilderFactory.get("stepInsert")
                .<Map<String, String>, Map<String, String>>chunk(1)
                .reader(readerByMyBatis())
                .writer(batChunkWriter)
                .transactionManager(dbWriteManager)
                .allowStartIfComplete(true)
                .build();
    }
}
 
6. 测试:
三. 代码下载:SpringBatch Sample



















