Introduction au lot de printemps
1. introduction
Dans cet article, nous allons nous concentrer sur une introduction pratique et axée sur le code à Spring Batch. Spring Batch est une infrastructure de traitement conçue pour une exécution robuste des travaux.
Il s'agit de la version 3.0 actuelle, qui prend en charge Spring 4 et Java 8. Il prend également en charge JSR-352, qui est une nouvelle spécification Java pour le traitement par lots.
Here are quelques cas d'utilisation intéressants et pratiques du framework.
2. Principes de base du workflow
Spring batch est conforme à l'architecture de lot traditionnelle dans laquelle un référentiel de travaux effectue le travail de planification et d'interaction avec le travail.
Une tâche peut comporter plusieurs étapes - et chaque étape suit généralement la séquence de lecture, de traitement et d'écriture des données.
Et bien sûr, le framework fera le gros du travail pour nous ici - en particulier en ce qui concerne le travail de persistance de bas niveau de gestion des jobs - en utilisantsqlite pour le référentiel de jobs.
2.1. Notre exemple d'utilisation
Le cas d'utilisation simple que nous allons aborder ici est le suivant: nous allons migrer certaines données de transactions financières de CSV vers XML.
Le fichier d'entrée a une structure très simple: il contient une transaction par ligne, composée de: un nom d'utilisateur, l'identifiant de l'utilisateur, la date de la transaction et le montant:
username, userid, transaction_date, transaction_amount
devendra, 1234, 31/10/2015, 10000
john, 2134, 3/12/2015, 12321
robin, 2134, 2/02/2015, 23411
3. Le Maven POM
Les dépendances requises pour ce projet sont spring core, spring batch etsqlite jdbc connector:
4.0.0
org.example
spring-batch-intro
0.1-SNAPSHOT
jar
spring-batch-intro
http://maven.apache.org
UTF-8
4.2.0.RELEASE
3.0.5.RELEASE
3.8.11.2
org.xerial
sqlite-jdbc
${sqlite.version}
org.springframework
spring-oxm
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework.batch
spring-batch-core
${spring.batch.version}
4. Configuration du lot de printemps
La première chose que nous allons faire est de configurer Spring Batch avec XML:
Bien sûr, une configuration Java est également disponible:
@Configuration
@EnableBatchProcessing
public class SpringConfig {
@Value("org/springframework/batch/core/schema-drop-sqlite.sql")
private Resource dropReopsitoryTables;
@Value("org/springframework/batch/core/schema-sqlite.sql")
private Resource dataReopsitorySchema;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:repository.sqlite");
return dataSource;
}
@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
throws MalformedURLException {
ResourceDatabasePopulator databasePopulator =
new ResourceDatabasePopulator();
databasePopulator.addScript(dropReopsitoryTables);
databasePopulator.addScript(dataReopsitorySchema);
databasePopulator.setIgnoreFailedDrops(true);
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator);
return initializer;
}
private JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
factory.afterPropertiesSet();
return (JobRepository) factory.getObject();
}
private PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
public JobLauncher getJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
5. Configuration du travail par lots de printemps
Écrivons maintenant notre description de poste pour le travail CSV vers XML:
org.example.spring_batch_intro.model.Transaction
Et bien sûr, la configuration de travail similaire basée sur Java:
public class SpringBatchConfig {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Value("input/record.csv")
private Resource inputCsv;
@Value("file:xml/output.xml")
private Resource outputXml;
@Bean
public ItemReader itemReader()
throws UnexpectedInputException, ParseException {
FlatFileItemReader reader = new FlatFileItemReader();
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
String[] tokens = { "username", "userid", "transactiondate", "amount" };
tokenizer.setNames(tokens);
reader.setResource(inputCsv);
DefaultLineMapper lineMapper =
new DefaultLineMapper();
lineMapper.setLineTokenizer(tokenizer);
lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
reader.setLineMapper(lineMapper);
return reader;
}
@Bean
public ItemProcessor itemProcessor() {
return new CustomItemProcessor();
}
@Bean
public ItemWriter itemWriter(Marshaller marshaller)
throws MalformedURLException {
StaxEventItemWriter itemWriter =
new StaxEventItemWriter();
itemWriter.setMarshaller(marshaller);
itemWriter.setRootTagName("transactionRecord");
itemWriter.setResource(outputXml);
return itemWriter;
}
@Bean
public Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(new Class[] { Transaction.class });
return marshaller;
}
@Bean
protected Step step1(ItemReader reader,
ItemProcessor processor,
ItemWriter writer) {
return steps.get("step1"). chunk(10)
.reader(reader).processor(processor).writer(writer).build();
}
@Bean(name = "firstBatchJob")
public Job job(@Qualifier("step1") Step step1) {
return jobs.get("firstBatchJob").start(step1).build();
}
}
OK, maintenant que nous avons la configuration complète, décomposons-la et commençons à en discuter.
5.1. Lire des données et créer des objets avecItemReader
Nous avons d'abord configuré lescvsFileItemReader qui liront les données desrecord.csv et les convertiront en objetTransaction:
@SuppressWarnings("restriction")
@XmlRootElement(name = "transactionRecord")
public class Transaction {
private String username;
private int userId;
private Date transactionDate;
private double amount;
/* getters and setters for the attributes */
@Override
public String toString() {
return "Transaction [username=" + username + ", userId=" + userId
+ ", transactionDate=" + transactionDate + ", amount=" + amount
+ "]";
}
}
Pour ce faire, il utilise un mappeur personnalisé:
public class RecordFieldSetMapper implements FieldSetMapper {
public Transaction mapFieldSet(FieldSet fieldSet) throws BindException {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Transaction transaction = new Transaction();
transaction.setUsername(fieldSet.readString("username"));
transaction.setUserId(fieldSet.readInt(1));
transaction.setAmount(fieldSet.readDouble(3));
String dateString = fieldSet.readString(2);
try {
transaction.setTransactionDate(dateFormat.parse(dateString));
} catch (ParseException e) {
e.printStackTrace();
}
return transaction;
}
}
5.2. Traitement des données avecItemProcessor
Nous avons créé notre propre processeur d'élément,CustomItemProcessor. Cela ne traite rien lié à l'objet de transaction - il ne fait que transmettre l'objet d'origine provenant du lecteur au rédacteur:
public class CustomItemProcessor implements ItemProcessor {
public Transaction process(Transaction item) {
return item;
}
}
5.3. Ecriture d'objets sur le FS avecItemWriter
Enfin, nous allons stocker cetransaction dans un fichier xml situé àxml/output.xml:
5.4. Configuration du travail par lots
Donc, tout ce que nous avons à faire est de relier les points à un travail - en utilisant la syntaxebatch:job.
Notez lescommit-interval - c'est le nombre de transactions à conserver en mémoire avant de valider le lot vers lesitemWriter; il gardera les transactions en mémoire jusqu'à ce point (ou jusqu'à ce que la fin des données d'entrée soit rencontrée):
5.5. Exécution du travail par lots
C'est tout - configurons et exécutons maintenant tout:
public class App {
public static void main(String[] args) {
// Spring Java config
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(SpringConfig.class);
context.register(SpringBatchConfig.class);
context.refresh();
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("firstBatchJob");
System.out.println("Starting the batch job");
try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Job Status : " + execution.getStatus());
System.out.println("Job completed");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Job failed");
}
}
}
6. Conclusion
Ce tutoriel vous donne une idée de base dehow to work with Spring Batch et comment l'utiliser dans un cas d'utilisation simple.
Il montre comment vous pouvez facilement développer votre pipeline de traitement par lots et comment personnaliser différentes étapes de lecture, de traitement et d’écriture.
Lesfull implementation de ce didacticiel se trouvent dansthe github project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.