简体   繁体   English

Spring Boot批处理调度程序运行一次

[英]Spring boot batch scheduler run once

I started to learn Spring Boot Batch in version 2.1.4 我开始在2.1.4版本中学习Spring Boot Batch

I want to run my job in scheduler and this job runs only once. 我想在调度程序中运行我的工作,而该工作仅运行一次。 I mean ItemProcessor and ItemWriter run only once. 我的意思是ItemProcessor和ItemWriter仅运行一次。 ItemReader runs every time. ItemReader每次都会运行。 anyone have an idea what I did wrong. 任何人都知道我做错了什么。 In the future, I want to change scheduler to Java WatchService and pass filePath to the job but now parameter for filePath is like a string in the function parameter. 将来,我想将调度程序更改为Java WatchService,并将filePath传递给作业,但现在filePath的参数就像function参数中的字符串一样。 This is my code: 这是我的代码:

This is my reader: 这是我的读者:

@Component
public class UserReaderImpl  {
    @StepScope
    public ItemReader<UserCsvStructure> read(String filepath) {
        FlatFileItemReader<UserCsvStructure> reader = new FlatFileItemReader();
        reader.setLinesToSkip(1);
        reader.setResource(new FileSystemResource(filepath));
        reader.setLineMapper(new DefaultLineMapper<UserCsvStructure>() {
            {
                setLineTokenizer(new DelimitedLineTokenizer() {
                    {
                        setNames(new String[]{"firstName","lastName","email"});
                    }
                });
                setFieldSetMapper(new BeanWrapperFieldSetMapper<UserCsvStructure>() {
                    {
                        setTargetType(UserCsvStructure.class);
                    }
                });
            }
        });
        return reader;
    }
}

This in my ItemProcessor 这在我的ItemProcessor中

@StepScope
@Component
public class UserProcessorImpl implements ItemProcessor<UserCsvStructure, User> {
@Override
public User process(UserCsvStructure userCsvStructure) throws Exception {
    return User.builder()
            .email(userCsvStructure.getEmail())
            .firstName(userCsvStructure.getFirstName())
            .lastName(userCsvStructure.getLastName())
            .build();
}
}

This is my ItemWriter 这是我的ItemWriter

@Component
@StepScope
public class UserWriterImpl implements ItemWriter<User>{
@Autowired
private UserRepository userRepository;

@Override
public void write(List<? extends User> list) throws Exception {
    System.out.println(list);
    userRepository.saveAll(list);
}
}

And this is my configuration 这是我的配置

@Component
public class UserBatchCsvConfig {

@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;

@Autowired
private UserReaderImpl userReader;

@Autowired
private UserWriterImpl userWriter;

@Autowired
private UserProcessorImpl userProcessor;

public Job csvFileToDatabaseJob(UserJobCompletionNotificationListener listener, String fileName) {
    return jobBuilderFactory.get("userCsvProcess")
            .incrementer(new RunIdIncrementer())
            .listener(listener)
            .flow(csvFileToDatabaseStep(fileName))
            .end()
            .build();
}

private Step csvFileToDatabaseStep(String fileName) {
    return stepBuilderFactory.get("userCsvProcess")
            .<UserCsvStructure, User>chunk(1)
            .reader(userReader.read(fileName))
            .processor(userProcessor)
            .writer(userWriter)
            .build();
}

}

Last class is my scheduler: 最后一课是我的调度程序:

@Component
public class UserCsvProcessor {

@Autowired
private JobLauncher jobLauncher;

@Autowired
private UserBatchCsvConfig job;

@Autowired
private UserJobCompletionNotificationListener userJobCompletionNotificationListener;

@Scheduled(fixedDelay = 10000)
public void runJob() throws Exception {
    jobLauncher.run(job.csvFileToDatabaseJob(userJobCompletionNotificationListener, "C:\\Users\\Anik\\Desktop\\angular\\test.csv"), new JobParameters());
}
}

I know what should I add in my code In UserCsvProcessor class I need to change my scheduled function to: 我知道我应该在代码中添加些什么在UserCsvProcessor类中,我需要将计划的函数更改为:

@Scheduled(fixedDelay = 10000)
public void runJob() throws Exception {
    JobParameters params = new JobParametersBuilder()
            .addString("JobID", String.valueOf(System.currentTimeMillis()))
            .toJobParameters();
    jobLauncher.run(job.csvFileToDatabaseJob(userJobCompletionNotificationListener, "C:\\Users\\Anik\\Desktop\\angular\\test.csv"), params);
}

If someone has other idea or better idea just add an answer 如果有人有其他想法或更好的想法,只需添加答案

With the configuration you have in @Scheduled annotation you are indicating to be executed every 10 seconds. 使用@Scheduled批注中的配置时,表示每10秒执行一次。 So, when your first execution is completed it will wait 10 seconds and then execute it again and so on. 因此,当您的第一次执行完成时,它将等待10秒钟,然后再次执行,依此类推。

@Scheduled(fixedDelay = 10000)

If you want to execute it once (I guess it is once a day) you can use cron expression in your @Scheduled annotation. 如果要执行一次(我想每天执行一次),则可以在@Scheduled批注中使用cron表达式。 Check the example below where the cron expression indicates that the method should be executed every day at 10:15 am 检查下面的示例,其中cron表达式指示该方法应每天在上午10:15执行。

@Scheduled(cron = "0 15 10 * * *")

If you want to run it once a month/year you can handle the cron expression to do that. 如果您想每月/每年运行一次,则可以处理cron表达式来执行此操作。 Additionally, you can read that expression from the configuration file using something like the following: 此外,您可以使用以下类似内容从配置文件中读取该表达式:

@Scheduled(cron = "${cron.expression}")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM