Spring integration Spring集成&x2B;春季批处理:作业不会停止

Spring integration Spring集成&x2B;春季批处理:作业不会停止,spring-integration,spring-batch,Spring Integration,Spring Batch,我想从ftp服务器读取文件,然后将其保存到本地存储库并从服务器中删除,运行读取文件的作业,在DB上查找一条记录,更改一个参数并保存它 出了什么问题:工作没有完成;多次增加工资并为员工节省开支 Spring集成配置: @Bean public FtpInboundFileSynchronizer ftpInboundFileSynchronizer(DefaultFtpSessionFactory sessionFactory) { FtpInboundFileSy

我想从ftp服务器读取文件,然后将其保存到本地存储库并从服务器中删除,运行读取文件的作业,在DB上查找一条记录,更改一个参数并保存它

出了什么问题:工作没有完成;多次增加工资并为员工节省开支

Spring集成配置:

    @Bean
    public FtpInboundFileSynchronizer ftpInboundFileSynchronizer(DefaultFtpSessionFactory sessionFactory) {
        FtpInboundFileSynchronizer fileSynchronizer = new FtpInboundFileSynchronizer(sessionFactory);
        fileSynchronizer.setRemoteDirectory(remoteDirectory);
        fileSynchronizer.setDeleteRemoteFiles(true);
        return fileSynchronizer;
    }

    @Bean
    @InboundChannelAdapter(value = "fileInputChannel", poller = @Poller(cron = "*/5 * * * * ?"))
    public FtpInboundFileSynchronizingMessageSource ftpInboundFileSynchronizingMessageSource(FtpInboundFileSynchronizer fileSynchronizer) throws Exception {
        FtpInboundFileSynchronizingMessageSource messageSource = new FtpInboundFileSynchronizingMessageSource(fileSynchronizer);
        messageSource.setAutoCreateLocalDirectory(true);
        messageSource.setLocalDirectory(new File(localDirectory));
        messageSource.setLocalFilter(new AcceptOnceFileListFilter<>());
        return messageSource;
    }

    @Bean
    @ServiceActivator(inputChannel = "fileInputChannel")
    public FileWritingMessageHandler fileWritingMessageHandler() {
        FileWritingMessageHandler messageHandler = new FileWritingMessageHandler(new File(localDirectory));
        messageHandler.setOutputChannelName("jobLaunchRequestChannel");
        return messageHandler;
    }

    @ServiceActivator(inputChannel = "jobLaunchRequestChannel", outputChannel = "jobLaunchingGatewayChannel")
    public JobLaunchRequest jobLaunchRequest(File file) throws IOException {
        String[] content = FileUtils.readFileToString(file, "UTF-8").split("\\s+");
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("filename", file.getAbsolutePath())
                .addString("id", content[0]).addString("salary", content[1])
//                .addLong("time", System.currentTimeMillis())
                .toJobParameters();
        return new JobLaunchRequest(increaseSalaryJob, jobParameters);
    }

    @Bean
    @ServiceActivator(inputChannel = "jobLaunchingGatewayChannel")
    public JobLaunchingGateway jobLaunchingGateway(SimpleJobLauncher jobLauncher) {
        JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(jobLauncher);
        jobLaunchingGateway.setOutputChannelName("finish");
        return jobLaunchingGateway;
    }

    @ServiceActivator(inputChannel = "finish")
    public void finish() {
        System.out.println("FINISH");
    }
}
 @Bean
    public Job increaseSalaryJob(CustomJobListener listener, Step step1) {
        return jobBuilderFactory.get("increaseSalaryJob")
                .preventRestart()
                .listener(listener)
                .start(step1)
                .build();
    }

    @Bean
    public Step step1(ItemReader<Employee> reader) {
        return stepBuilderFactory.get("step1")
                .transactionManager(transactionManager)
                .<Employee, Employee> chunk(1)
                .reader(reader)
                .processor(processor())
                .writer(writer())
                .build();
    }

    @Bean
    @StepScope
    public ItemReader<Employee> reader(@Value("#{jobParameters[id]}") Integer id) {
        log.info("reader");
        return () -> employeeService.get(id);
    }

    @Bean
    @StepScope
    public ItemProcessor<Employee, Employee> processor() {
        log.info("processor");
        return employee -> {
            log.info(employee.getName() + " had salary " + employee.getSalary());
            Integer salary = employee.getSalary() + 1;
            employee.setSalary(salary);
            log.info(employee.getName() + " have salary " + employee.getSalary());

            return employee;
        };
    }

    @Bean
    @StepScope
    public ItemWriter<Employee> writer() {
        log.info("writer");
        return employees -> {
            for (Employee employee : employees) {
                try {
                    employeeService.update(employee);
                    log.info(employee.getName() + " updated with salary " + employee.getSalary());
                } catch (ValidationException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    @Bean
    public MapJobRepositoryFactoryBean jobRepositoryFactoryBean(PlatformTransactionManager transactionManager) {
        return new MapJobRepositoryFactoryBean(transactionManager);
    }

    @Bean
    public JobRepository jobRepository(MapJobRepositoryFactoryBean jobRepositoryFactoryBean) throws Exception {
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        return jobRepositoryFactoryBean.getObject();
    }

    @Bean
    public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        return jobLauncher;
    }
@Bean
公共FtpInboundFileSynchronizer FtpInboundFileSynchronizer(默认FTPSessionFactory会话工厂){
FtpInboundFileSynchronizer fileSynchronizer=新的FtpInboundFileSynchronizer(sessionFactory);
fileSynchronizer.setRemoteDirectory(remoteDirectory);
fileSynchronizer.setDeleteRemoteFiles(true);
返回文件同步器;
}
@豆子
@InboundChannelAdapter(value=“fileInputChannel”,poller=@poller(cron=“*/5****?”)
公共FtpInboundFileSynchronizingMessageSource FtpInboundFileSynchronizingMessageSource(FtpInboundFileSynchronizer fileSynchronizer)引发异常{
FtpInboundFileSynchronizingMessageSource=new-FtpInboundFileSynchronizingMessageSource(文件同步器);
messageSource.setAutoCreateLocalDirectory(true);
setLocalDirectory(新文件(localDirectory));
messageSource.setLocalFilter(新的AcceptOnceFileListFilter());
返回消息源;
}
@豆子
@ServiceActivator(inputChannel=“fileInputChannel”)
public FileWritingMessageHandler FileWritingMessageHandler(){
FileWritingMessageHandler messageHandler=新FileWritingMessageHandler(新文件(localDirectory));
setOutputChannelName(“jobLaunchRequestChannel”);
返回消息处理程序;
}
@ServiceActivator(inputChannel=“jobLaunchRequestChannel”,outputChannel=“jobLaunchingGatewayChannel”)
public JobLaunchRequest JobLaunchRequest(文件文件)引发IOException{
String[]content=FileUtils.readFileToString(文件“UTF-8”).split(\\s+”);
JobParameters JobParameters=新的JobParametersBuilder()
.addString(“文件名”,file.getAbsolutePath())
.addString(“id”,内容[0]).addString(“工资”,内容[1])
//.addLong(“时间”,System.currentTimeMillis())
.toJobParameters();
返回新的JobLaunchRequest(增加SalaryJob、jobParameters);
}
@豆子
@ServiceActivator(inputChannel=“jobLaunchingGatewayChannel”)
公共JobLaunchingGateway JobLaunchingGateway(SimpleJobLauncher jobLauncher){
JobLaunchingGateway JobLaunchingGateway=新JobLaunchingGateway(jobLauncher);
jobLaunchingGateway.setOutputChannelName(“完成”);
返回作业启动网关;
}
@ServiceActivator(inputChannel=“finish”)
公共空间整理(){
系统输出打印(“完成”);
}
}
Spring批处理配置:

    @Bean
    public FtpInboundFileSynchronizer ftpInboundFileSynchronizer(DefaultFtpSessionFactory sessionFactory) {
        FtpInboundFileSynchronizer fileSynchronizer = new FtpInboundFileSynchronizer(sessionFactory);
        fileSynchronizer.setRemoteDirectory(remoteDirectory);
        fileSynchronizer.setDeleteRemoteFiles(true);
        return fileSynchronizer;
    }

    @Bean
    @InboundChannelAdapter(value = "fileInputChannel", poller = @Poller(cron = "*/5 * * * * ?"))
    public FtpInboundFileSynchronizingMessageSource ftpInboundFileSynchronizingMessageSource(FtpInboundFileSynchronizer fileSynchronizer) throws Exception {
        FtpInboundFileSynchronizingMessageSource messageSource = new FtpInboundFileSynchronizingMessageSource(fileSynchronizer);
        messageSource.setAutoCreateLocalDirectory(true);
        messageSource.setLocalDirectory(new File(localDirectory));
        messageSource.setLocalFilter(new AcceptOnceFileListFilter<>());
        return messageSource;
    }

    @Bean
    @ServiceActivator(inputChannel = "fileInputChannel")
    public FileWritingMessageHandler fileWritingMessageHandler() {
        FileWritingMessageHandler messageHandler = new FileWritingMessageHandler(new File(localDirectory));
        messageHandler.setOutputChannelName("jobLaunchRequestChannel");
        return messageHandler;
    }

    @ServiceActivator(inputChannel = "jobLaunchRequestChannel", outputChannel = "jobLaunchingGatewayChannel")
    public JobLaunchRequest jobLaunchRequest(File file) throws IOException {
        String[] content = FileUtils.readFileToString(file, "UTF-8").split("\\s+");
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("filename", file.getAbsolutePath())
                .addString("id", content[0]).addString("salary", content[1])
//                .addLong("time", System.currentTimeMillis())
                .toJobParameters();
        return new JobLaunchRequest(increaseSalaryJob, jobParameters);
    }

    @Bean
    @ServiceActivator(inputChannel = "jobLaunchingGatewayChannel")
    public JobLaunchingGateway jobLaunchingGateway(SimpleJobLauncher jobLauncher) {
        JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(jobLauncher);
        jobLaunchingGateway.setOutputChannelName("finish");
        return jobLaunchingGateway;
    }

    @ServiceActivator(inputChannel = "finish")
    public void finish() {
        System.out.println("FINISH");
    }
}
 @Bean
    public Job increaseSalaryJob(CustomJobListener listener, Step step1) {
        return jobBuilderFactory.get("increaseSalaryJob")
                .preventRestart()
                .listener(listener)
                .start(step1)
                .build();
    }

    @Bean
    public Step step1(ItemReader<Employee> reader) {
        return stepBuilderFactory.get("step1")
                .transactionManager(transactionManager)
                .<Employee, Employee> chunk(1)
                .reader(reader)
                .processor(processor())
                .writer(writer())
                .build();
    }

    @Bean
    @StepScope
    public ItemReader<Employee> reader(@Value("#{jobParameters[id]}") Integer id) {
        log.info("reader");
        return () -> employeeService.get(id);
    }

    @Bean
    @StepScope
    public ItemProcessor<Employee, Employee> processor() {
        log.info("processor");
        return employee -> {
            log.info(employee.getName() + " had salary " + employee.getSalary());
            Integer salary = employee.getSalary() + 1;
            employee.setSalary(salary);
            log.info(employee.getName() + " have salary " + employee.getSalary());

            return employee;
        };
    }

    @Bean
    @StepScope
    public ItemWriter<Employee> writer() {
        log.info("writer");
        return employees -> {
            for (Employee employee : employees) {
                try {
                    employeeService.update(employee);
                    log.info(employee.getName() + " updated with salary " + employee.getSalary());
                } catch (ValidationException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    @Bean
    public MapJobRepositoryFactoryBean jobRepositoryFactoryBean(PlatformTransactionManager transactionManager) {
        return new MapJobRepositoryFactoryBean(transactionManager);
    }

    @Bean
    public JobRepository jobRepository(MapJobRepositoryFactoryBean jobRepositoryFactoryBean) throws Exception {
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        return jobRepositoryFactoryBean.getObject();
    }

    @Bean
    public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        return jobLauncher;
    }
@Bean
公共作业增量SalaryJob(CustomJobListener侦听器,步骤1){
返回jobBuilderFactory.get(“increaseSalaryJob”)
.防止重新启动()
.listener(侦听器)
.开始(步骤1)
.build();
}
@豆子
公共步骤步骤1(项目阅读器){
返回stepBuilderFactory.get(“step1”)
.transactionManager(transactionManager)
.chunk(1)
.读卡器(读卡器)
.processor(处理器())
.writer(writer())
.build();
}
@豆子
@步进镜
public ItemReader reader(@Value(“#{jobParameters[id]}”)整数id){
日志信息(“阅读器”);
return()->employeeService.get(id);
}
@豆子
@步进镜
公共项目处理器(){
日志信息(“处理器”);
返回员工->{
log.info(employee.getName()+“had salary”+employee.getSalary());
整数工资=employee.getSalary()+1;
员工薪酬(工资);
log.info(employee.getName()+“have salary”+employee.getSalary());
返回员工;
};
}
@豆子
@步进镜
公共项目编写器(){
日志信息(“作者”);
返回员工->{
用于(员工:员工){
试一试{
employeeService.update(员工);
log.info(employee.getName()+“更新为工资”+employee.getSalary());
}捕获(ValidationException e){
e、 printStackTrace();
}
}
};
}
@豆子
公共地图jobRepositoryFactoryBean jobRepositoryFactoryBean(PlatformTransactionManager transactionManager){
返回新的MapJobRepositoryFactoryBean(transactionManager);
}
@豆子
public JobRepository JobRepository(MapJobRepositoryFactoryBean jobRepositoryFactoryBean)引发异常{
setTransactionManager(transactionManager);
返回jobRepositoryFactoryBean.getObject();
}
@豆子
公共SimpleJobLauncher作业启动器(JobRepository JobRepository){
SimpleJobLauncher jobLauncher=新的SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
返回作业启动器;
}

我很乐意提供任何帮助。

您需要确保您的阅读器在某个时候返回
null
。这就是该步骤如何解释没有更多的数据要处理和退出(如果没有更多的步骤要运行,则会停止周围的作业)


也就是说,我看到面向块的步骤的输入是一个
id
。对于这个用例,一个简单的tasklet就足够了,不需要一个具有单个输入记录和
chunkSize=1

的面向块的tasklet,读者是否会在某个时候返回
null
?如果您为单个Id运行作业,一个简单的tasklet就足够了,不需要一个具有单个输入记录和chunkSi的面向块的tasklet