官网的例子基本都是基于XML配置的,在SpringBoot流行和简化开发的大环境下,再回过头去配置各种XML和手工Bean,会让SpringBoot使用失去了意义。这次尝试使用SpringBoot进行练习,看是否能简化开发。在官网的基础上进行了简单的变形,采用了Mysql8数据库,同时增加了定时器。启动两个定时器,纯粹就是为了调起多个Job实例,前面几篇文章有理论知识了,这里主要贴一些例子帮助快速入门。文末尾有源码,有需要的可以下载。
引入Spring Boot Batch,Mysql。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ycxy</groupId>
<artifactId>batchstudy04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>batchstudy04</name>
<description>job</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring:
datasource:
url: jdbc:mysql://192.168.172.200/spbatch02?serverTimezone=GMT
username: app
password: 1231231231231231
auto-commit: false
driver-class-name: com.mysql.cj.jdbc.Driver
# batch.job.enabled:true 服务器启动后会自动调用JobLauncher运行job
# 如果时false 不会自动运行Job,适合定时调用Job
batch:
job:
enabled: false
package com.ycxy.batchstudy04;
public class Person {
private String lastName;
private String firstName;
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "firstName: " + firstName + ", lastName: " + lastName;
}//纯粹是为了测试方便看数据
}
package com.ycxy.batchstudy04;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
public class PersonItemProcessor implements ItemProcessor<Person,Person> {
private static final Logger log = LoggerFactory.getLogger(PersonItemProcessor.class);
/**
* person 传入值
* @param person
* @return
* @throws Exception
*/
@Override
public Person process(Person person) throws Exception {
String firstName= person.getFirstName().toUpperCase();
String lastName = person.getLastName().toUpperCase();
Person transformedPerson = new Person(firstName, lastName);
log.info("Converting (" + person + ") into (" + transformedPerson + ")");
return transformedPerson;
}
}
package com.ycxy.batchstudy04;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import javax.sql.DataSource;
@Configuration
public class BatchJoba {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
DataSource dataSource;
@Bean
public FlatFileItemReader<Person> reader() {
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.names(new String[]{"firstName", "lastName"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}})
.build();
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public JdbcBatchItemWriter<Person> writer() {
return new JdbcBatchItemWriterBuilder<Person>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO PEOPLE (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataSource)
.build();
}
@Bean
public Job importUserJob() {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.next(step2())
.end()
.build();
}
@Bean
public Job importUserJob1() {
return jobBuilderFactory.get("importUserJob1")
.incrementer(new RunIdIncrementer())
.flow(step1())
.next(step2())
.end()
.build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
}
package com.ycxy.batchstudy04;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@EnableBatchProcessing
public class Batchstudy04Application {
public static void main(String[] args) {
SpringApplication.run(Batchstudy04Application.class, args);
}
}
封装一下Job执行任务
package com.ycxy.batchstudy04.service;
import org.springframework.batch.core.Job;
public interface BatchService {
public void createBatchJob(String taskId, Job job) throws Exception ;
}
package com.ycxy.batchstudy04.service;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service("batchService")
public class BatchServiceImpl implements BatchService {
// 框架自动注入
@Autowired
private JobLauncher jobLauncher;
/**
* 根据 taskId 创建一个Job
* @param taskId
* @throws Exception
*/
public void createBatchJob(String taskId,Job job) throws Exception {
JobParameters jobParameters = new JobParametersBuilder()
.addString("taskId", taskId)
.addString("uuid", UUID.randomUUID().toString().replace("-",""))
.toJobParameters();
// 传入一个Job任务和任务需要的参数
jobLauncher.run(job, jobParameters);
}
}
package com.ycxy.batchstudy04.schedule;
import com.ycxy.batchstudy04.service.BatchService;
import org.springframework.batch.core.Job;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 通过定制定时任务,启动不同的Job
*/
@Component
public class JobRunSchedule {
@Autowired
BatchService batchService;
@Autowired
private Job importUserJob;
@Autowired
private Job importUserJob1;
@Scheduled(fixedRate = 10000) // 表示 每隔 5000 毫秒执行一次
public void runScheduleJob(){
System.out.println("任务启动runScheduleJob");
try {
batchService.createBatchJob("simplePerson",importUserJob);
} catch (Exception e) {
e.printStackTrace();
}
}
@Scheduled(fixedRate = 3000) // 表示 每隔 3000 毫秒执行一次
public void runScheduleJob1(){
System.out.println("任务启动runScheduleJob1");
try {
batchService.createBatchJob("simplePerson",importUserJob1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
源码地址:
链接:https://pan.baidu.com/s/1fCnk5BSCw-RuQdEc7SqzRA
提取码:bhn0