springBatch
Spring Batch 结合 定时调度框架Quartz
https://www.cnblogs.com/larrydpk/p/13660537.html
https://blog.csdn.net/u012921921/article/details/105591216/ 多线程处理
Job Instance:作业实例
Job Parameter:作业参数
Job Execution:作业执行器
https://blog.csdn.net/a18792721831/article/details/109550018
spring.batch.job.enabled=false
spring.batch.initialize-schema=always
spring.datasource.url=jdbc:mysql://127.0.0.1/xmh
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
@SpringBootApplication
@EnableBatchProcessing
SimpleBatchConfiguration
官方: http://www.springsource.org/spring-batch
springBatch待处理:
数据分块,并发处理 远程分块
事物机制
REFERENCES command denied to user 'pahapp'@'10.131.39.87' for table 'batch_job_instance'
spring batch官方文档:https://docs.spring.io/spring-batch
spring batch3.x中文文档:http://www.kailing.pub/SpringBatchReference
spring batch官方入门实例:https://projects.spring.io/spring-batch/
https://www.bbsmax.com/A/8Bz88QV6zx/
手动启动一个job 传入参数
停止一个job
事物 https://blog.csdn.net/neweastsun/article/details/88866837
概念:
JobParameters 一次任务job执行,任务链上的参数
Tasklet 任务的一种实现方式,其他还有Chunks实现
任务场景1:
Chunks实现,一个job任务里,读、处理、写分开共同组成一个step
任务场景2:
Tasklet实现,一个job任务里,由多个step按先后顺序组成
优点:
1,接口、任务job、step管理
2,并行的step处理
3,批处理的精细化管理,元数据存放在数据库中,可以随时监控批处理Job的执行状态
4,可重启性
Job执行期间如果因为异常导致失败,应该能够在失败的点重新启动Job;而不是从头开始重新执行Job。
要点:
1,同一个参数只能启动一次任务 A job instance already exists and is complete for parameters={myParamter=myParamter1111111111111}
jobLauncher.run(MyJob(), parameters);//启动任务
2,面向“块”的step中chunk(2) 一次读取、处理、写入的条数
spring.batch.job.enabled=false来禁止Spring容器自动启动Job
面向“块”的step,有ItemReader, ItemProcessor, 和 ItemWriter 这3个接口
读完以后返回null,job就会自动停下来了
3,多线程step,并行step https://www.cnblogs.com/larrydpk/p/13664256.html
https://www.cnblogs.com/rookiemzl/p/9788002.html
Job Instance(作业实例)是一个运行期的概念,Job每执行一次都会涉及到一个Job Instance。
Job Instance来源可能有两种:一种是根据设置的Job Parameters从Job Repository(作业仓库)中获取一个;如果根据Job Parameters从Job Repository没有获取Job Instance,则新创建一个新的Job Instance。
Job Execution表示Job执行的句柄,一次Job的执行可能成功也可能失败。只有Job执行成功后,对应的Job Instance才会被完成。因此在Job执行失败的情况下,会有一个Job Instance对应多个Job Execution的场景发生。
这里就能明显看到之前设置的chunk的作用了。Writer每次是处理5条记录,如果一条输出一次,会对IO造成压力。
Job Repository来存储Job执行期的元数据(这里的元数据是指Job Instance、Job Execution、Job Parameters、Step Execution、Execution Context等数据),并提供两种默认实现。
一种是存放在内存中;另一种将元数据存放在数据库中。通过将元数据存放在数据库中,可以随时监控批处理Job的执行状态。Job执行结果是成功还是失败,并且使得在Job失败的情况下重新启动Job成为可能。Step表示作业中的一个完整步骤,一个Job可以有一个或者多个Step组成。
框架在Job层面,同样提供了作业编排的概念,包括顺序、条件、并行作业编排。
Chunk支持事务管理,通过commit-interval设置每次提交的记录数;Step的每一次提交作为一个完整的事务存在
Remote Chunking
远程Step技术本质上是将对Item读、写的处理逻辑进行分离;通常情况下读的逻辑放在一个节点进行操作,将写操作分发到另外的节点执行。
分区处理
通过数据分区后,不同的数据已经被分配到不同的作业步执行器中
@Configuration
@EnableBatchProcessing
public class JobDemo implements StepExecutionListener{
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private JobOperator jobOperator;
@Autowired
private JobRepository jobRepository;
@Autowired
private JobRegistry jobRegistry;
@Autowired
private JobExplorer jobExplorer;
@Autowired
private ApplicationContext context;//或者implements ApplicationContextAware 通过构造注入
//创建一个成员变量
private Map<String,JobParameter> parameters;
// .start(readLines())
// .next(processLines())
// .next(writeLines())
@Bean("demo")
public Job jobDemo() {
return jobBuilderFactory.get("demo").start(step1()).on("COMPLETED")
.to(step2()).from(step2()).on("COMPLETED")
.to(step3()).from(step3()).end()
.build();
}
public Step step3() {
return stepBuilderFactory.get("step3").tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("================step3==============:");
return RepeatStatus.FINISHED;
}
}).build();
}
public Step step2() {
return stepBuilderFactory.get("step2").tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("================step2==============");
return RepeatStatus.FINISHED;
}
}).build();
}
public Step step1() {
return stepBuilderFactory.get("step1").listener(this).tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("================step1==============:"+parameters.get("myParamter").getValue());
return RepeatStatus.FINISHED;
}
}).build();
}
public void lunch(String paramter) throws Exception {
JobParameters parameters = new JobParametersBuilder()
.addString("myParamter", paramter)//添加参数
.toJobParameters();
jobLauncher.run(jobDemo(), parameters);//启动任务
// jobOperator.start("jobDemo", "meg=" + "");//jobOperator需要自己定义
//自定义的jobOperator需要自己定义
/*SimpleJobOperator jobOperator = new SimpleJobOperator();
jobOperator.setJobLauncher(jobLauncher);
jobOperator.setJobParametersConverter(new DefaultJobParametersConverter());//参数转换器
jobOperator.setJobRepository(jobRepository);//jobRepository持久化
jobOperator.setJobExplorer(jobExplorer);//jobExplorer获取和任务相关的信息
jobOperator.setJobRegistry(jobRegistry);//注册,需要创建,根据job名称获取job对象
*/
}
// @Bean
// public JobRegistryBeanPostProcessor registryBeanPostProcessor() throws Exception {
// JobRegistryBeanPostProcessor registryBeanPostProcessor = new JobRegistryBeanPostProcessor();
// registryBeanPostProcessor.setJobRegistry(jobRegistry);
// registryBeanPostProcessor.setBeanFactory(context.getAutowireCapableBeanFactory());
// registryBeanPostProcessor.afterPropertiesSet();
// return registryBeanPostProcessor;
// }
@Override
public void beforeStep(StepExecution stepExecution) {
this.parameters = stepExecution.getJobParameters().getParameters();
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}
测试入口
jobDemo.lunch("myParamter1111111111111");
@Configuration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
private JobLauncher jobLauncher;
@Bean
public MyItemProcessor processor(){
return new MyItemProcessor();
}
@Bean
public ItemWriter<String> writer(){
return new MyItemWriter();
}
// @Bean
// public ItemReader<String> textReader(){
// FlatFileItemReader<String> reader=new FlatFileItemReader<>();
// File file = new File("D:\\FTP\\ttest.txt");
// reader.setResource(new FileSystemResource(file));
// reader.setLineMapper(new LineMapper<String>() {
// @Override
// public String mapLine(String line, int lineNumber) throws Exception {
// return line;
// }
// });
// return reader;
// }
@Bean
@StepScope
public ItemReader<String> stringReader(@Value("#{jobParameters[myParamter]}") String param){
return new MyItemReader(param);
}
@Override
public void setDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
@Bean
public Step myStep(){
return stepBuilderFactory
.get("step1")
//这个chunk size是最后调用写入的时候,一次性写入多少条已处理的数据
.<String,String>chunk(2)
// .reader(textReader())
.reader(stringReader(""))
.processor(processor())
.writer(writer())
.listener(new ItemWriteListener<String>(){
@Override
public void beforeWrite(List<? extends String> list) {
System.out.println("beforeWrite:"+list);
}
@Override
public void afterWrite(List<? extends String> list) {
System.out.println("afterWrite:"+list);
}
@Override
public void onWriteError(Exception e, List<? extends String> list) {
}
})
.build();
}
@Bean
public Job MyJob(){
return jobBuilderFactory
.get("MyJOB")
.listener(new JobExecutionListenerSupport(){
@Override
public void beforeJob(JobExecution jobExecution) {
System.out.println("beforeJob执行执行做处理");
}
//所有处理结束后调用
@Override
public void afterJob(JobExecution jobExecution) {
System.out.println("afterJob执行执行做处理");
if(jobExecution.getStatus() == BatchStatus.COMPLETED){
System.out.println("JobExecutionListenerSupport*****OK");
}
}
})
.flow(myStep())
.end()
.build();
}
//同一个参数只能启动一次任务 A job instance already exists and is complete for parameters={myParamter=myParamter1111111111111}
public void lunch(String paramter) throws Exception {
JobParameters parameters = new JobParametersBuilder()
.addString("myParamter", paramter)//添加参数
.toJobParameters();
jobLauncher.run(MyJob(), parameters);//启动任务
}
}
public class MyItemReader implements ItemReader<String> {
private int i;
private String param;
public MyItemReader(String param) {
this.param = param;
}
@Override
public String read() throws Exception{
System.out.println("MyItemReader:"+param);
if(i >= 3){
return null;
}
i++;
return param;
}
}
public class MyItemProcessor implements ItemProcessor<String,String> {
public Object processItem(Object o) throws Exception {
return null;
}
@Override
public String process(String s) throws Exception {
System.out.println("MyItemProcessor:"+s);
return s+"---------PROCESSED";
}
}
public class MyItemWriter implements ItemWriter<String> {
@Override
public void write(List<? extends String> items) throws Exception {
for (String item : items) {
System.out.println("MyItemWriter:"+item);
}
}
}
元数据存储到数据库
@Bean
public DataSource dataSourceMy(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://10.20.25.138:3307/db_pajkx_sportaward?zeroDateTimeBehavior=convertToNull");
dataSource.setPassword("123456");
dataSource.setUsername("pahapp");
return dataSource;
}
@Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
System.out.println("***************************jobRepository:datasource:"+dataSourceMy()+",this.getTransactionManager():"+this.getTransactionManager()
+",transactionManager:"+transactionManager);
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSourceMy());
factory.setTransactionManager(transactionManager);
// factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");//ISOLATION_SERIALIZABLE SERIALIZABLE
factory.setTablePrefix("BATCH_");
factory.setMaxVarCharLength(1000);
return factory.getObject();
}
@Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(jobRepository);
return simpleJobLauncher;
}
@Autowired
JobLauncher jobLauncher;
@Autowired
@Qualifier("myJob")
Job myJob;
JobParameters parameters = new JobParametersBuilder()
.addString("myParamter", request.getUserId())//添加参数
.toJobParameters();
jobLauncher.run(myJob, parameters);//启动任务
元数据存储到内存
@Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager);
mapJobRepositoryFactoryBean.setTransactionManager(transactionManager);
return mapJobRepositoryFactoryBean.getObject();
}
@Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(jobRepository);
return simpleJobLauncher;
}

浙公网安备 33010602011771号