pom文件:
批处理包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency>
定时任务包
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency>
启动类加载定时任务:
@EnableScheduling
@Bean public SchedulerFactory schedulerFactory() { return new org.quartz.impl.StdSchedulerFactory(); }
@Bean public Scheduler scheduler() throws SchedulerException { return schedulerFactory().getScheduler(); }
SpringBatch 三大核心:
1、读数据Reader;
2、处理数据Processor;
3、写数据Writer;
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 org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; public class BatchReader implements ItemReader<Object> { @Override public FlatFileItemReader<Music> read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { String filePath = "D:\\music.csv"; FlatFileItemReader<Music> reader = new FlatFileItemReader<>(); Resource resource = new FileSystemResource(filePath); reader.setResource(resource); BeanWrapperFieldSetMapper fieldSetMapper = new BeanWrapperFieldSetMapper(); fieldSetMapper.setTargetType(Music.class); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); tokenizer.setDelimiter(","); tokenizer.setNames("id", "com_code"); DefaultLineMapper<Music> lineMapper = new DefaultLineMapper<>(); lineMapper.setFieldSetMapper(fieldSetMapper); lineMapper.setLineTokenizer(tokenizer); reader.setLineMapper(lineMapper); return reader; } }
Processor:
import org.springframework.batch.item.ItemProcessor; /** * 处理业务数据 */ public class BatchProcessor implements ItemProcessor<Music, Music> { @Override public Music process(Music item) throws Exception { System.out.println("in [BatchProcessor], processing credit bill ... "); return item; } }
Writer:
import ins.framework.utils.Beans; import ins.platform.part.partloc.dao.BrandToModelDao; import org.springframework.batch.item.ItemWriter; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * 批量写入业务数据 */ public class BatchWriter implements ItemWriter<Music> { @Autowired BrandToModelDao brandToModelDao; @Override public void write(List<? extends Music> items) throws Exception { List<Music> aaMusics = Beans.copyDepth().from(items).toList(Music.class); brandToModelDao.batchSave(aaMusics); } }
配置类:
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.ItemWriter; import org.springframework.batch.item.NonTransientResourceException; import org.springframework.batch.item.ParseException; import org.springframework.batch.item.UnexpectedInputException; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableBatchProcessing // 开启批处理的支持 public class BatchConfig { @Autowired private JobBuilderFactory jobBuilderFactory; @Autowired private StepBuilderFactory stepBuilderFactory; /** 读取业务数据 */ @Bean public FlatFileItemReader<Music> batchReader()throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { return new BatchReader().read(); } /** 处理业务数据 */ @Bean public BatchProcessor createProcessor(){ return new BatchProcessor(); } /** 批量写入业务数据 */ @Bean public ItemWriter<Music> batchWriter(){ return new BatchWriter(); } /** * 将数据写入数据库 */ @Bean public Job createJob()throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException{ return jobBuilderFactory.get("Job").start(createStep()).build(); } @Bean public Step createStep()throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException{ return stepBuilderFactory.get("Step") .<Music, Music>chunk(2)//每次读取条数 .reader(batchReader())//读取数据 .processor(createProcessor())//处理数据 .writer(batchWriter())//写数据 .build(); } } 实体类: import lombok.Data; import java.io.Serializable; @Data public class Music implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String comCode; }
定时任务:
/** * 批处理 */ @Async @Scheduled(cron="*/5 * 0-23 * * ?") public void batchData() { log.info("批处理定时任务开始"); try { log.info("IP = {},获取到分布式锁,开始执行任务:{}", ip); try{ JobParametersBuilder paramBuilder = new JobParametersBuilder(); paramBuilder.addLong("DS", System.currentTimeMillis()); JobExecution jobExecution = launcher.run(importJob, paramBuilder.toJobParameters()); System.out.println("JobExecution : " + jobExecution.toString()); } catch (Exception e){ e.printStackTrace(); } } catch (Exception e) { log.error("IP = {},获取到分布式锁,执行任务:{}失败,原因:{}", ip, e); } finally { // 释放共享锁 //stringRedisTemplate.delete(autoJobKey); log.info("批处理定时任务结束"); } }
xml:
<insert id="batchSave" useGeneratedKeys="true" keyProperty="id" parameterType="map"> INSERT INTO music (id, com_code) VALUES <foreach collection="list" item="item" index="index" separator=","> (#{item.id},#{item.comCode}) </foreach> </insert>
dao:
int batchSave(@Param("list")List<Music> list);
yml配置:
spring.batch.initialize-schema = always
spring.batch.job.enabled = false