【问题标题】:Spring batch job runs automaticallySpring批处理作业自动运行
【发布时间】:2021-01-15 20:24:09
【问题描述】:

我正在使用弹簧批处理读取 CSV 文件并将其写入数据库,使用控制器触发器。在启动应用程序时,在我点击浏览器 url 之前,我会在启动时看到来自阅读器的打印语句。尽管它不会为我的处理器或编写器打印它,它们位于我已自动装配的单独类中。是因为阅读器是豆子吗?

我在应用程序启动的日志中看到来自我的FlatFileItemReader 的打印语句。但是,只有当我点击控制器 URL 时,我的处理器和编写器的打印语句才会显示在控制台中。 我尝试在application.properties 文件中添加spring.batch.job.enabled=false,但它不会停止阅读器bean 的执行。如何防止 SpringBatchConfig 类中读取器 bean 的自动执行:

SpringBatchConfig 类:

@Configuration
@EnableBatchProcessing
public class SpringBatchConfig {
    
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    
    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private DBWriter writer1;
    
    @Autowired
    private Processor processor1;
    
    //Step 1 - CSV to DB
    @Bean
    public FlatFileItemReader<User> itemReader() {

        FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
        flatFileItemReader.setResource(new FileSystemResource("src/main/resources/users.csv"));
        flatFileItemReader.setName("CSV-Reader");
        flatFileItemReader.setLinesToSkip(1);
        flatFileItemReader.setLineMapper(lineMapper());
        System.out.println("inside file reader 1 !!!!!");
        return flatFileItemReader;
    }

    @Bean
    public LineMapper<User> lineMapper() {

        DefaultLineMapper<User> defaultLineMapper = new DefaultLineMapper<>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();

        lineTokenizer.setDelimiter(",");
        lineTokenizer.setStrict(false);
        lineTokenizer.setNames(new String[]{"id", "name", "dept", "salary"});

        BeanWrapperFieldSetMapper<User> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(User.class);

        defaultLineMapper.setLineTokenizer(lineTokenizer);
        defaultLineMapper.setFieldSetMapper(fieldSetMapper);

        return defaultLineMapper;
    }

    @Bean
    public Step step1() throws Exception{   // Step 1 - Read CSV and Write to DB
        return stepBuilderFactory.get("step1")
                .<User,User>chunk(100)
                .reader(itemReader())
                .processor(processor1)
                .writer(writer1)
                .build();
    }

   @Bean
    public Job job() throws Exception{
        return this.jobBuilderFactory.get("BATCH JOB")
                .incrementer(new RunIdIncrementer())
                .start(step1())
                .build();
    }

DBWriter 类:

@Component
public class DBWriter implements ItemWriter<User> {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void write(List<? extends User> users) throws Exception {
    System.out.println("Inside DB Writer");
        System.out.println("Data Saved for Users: " + users);
            userRepository.save(users);
    }
}

处理器类:

@Component
public class Processor implements ItemProcessor<User, User> {

    private static final Map<String, String> DEPT_NAMES =
            new HashMap<>();

    public Processor() {
        DEPT_NAMES.put("001", "Technology");
        DEPT_NAMES.put("002", "Operations");
        DEPT_NAMES.put("003", "Accounts");
    }

    @Override
    public User process(User user) throws Exception {
        String deptCode = user.getDept();
        String dept = DEPT_NAMES.get(deptCode);
        user.setDept(dept);
        user.setTime(new Date());
        System.out.println(String.format("Converted from [%s] to [%s]", deptCode, dept));
        return user;
    }
}

控制器类:

@RestController
@RequestMapping("/load")
public class LoadController {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job job;

    @GetMapping("/users")
    public BatchStatus load() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {


        Map<String, JobParameter> maps = new HashMap<>();
        maps.put("time", new JobParameter(System.currentTimeMillis()));
        JobParameters parameters = new JobParameters(maps);
        JobExecution jobExecution = jobLauncher.run(job, parameters);

        System.out.println("JobExecution: " + jobExecution.getStatus());

        System.out.println("Batch is Running...");
        while (jobExecution.isRunning()) {
            System.out.println("...");
        }

        return jobExecution.getStatus();
    }
}

【问题讨论】:

  • 是的,这是因为 Bean 注释。它在配置阶段执行。我认为您不需要 Bean 注释。删除它,它应该可以正常工作。
  • @SaiKarthik 我也试过了。没用。

标签: java spring spring-boot spring-batch


【解决方案1】:

spring.batch.job.enabled=false 属性用于防止在应用程序启动时运行作业。

创建阅读器的方法仍然会在配置时被调用,所以看到打印语句是正常的。但这并不意味着读取器是在正在运行的作业中调用的。

【讨论】:

  • 公平。此外,记录器语句也会发生同样的情况。当我点击网址时,阅读器中的内容不会打印。处理器和作家中的那些。有没有办法让它们在通过 url 触发时全部打印出来?
  • 我也在Tomcat started at port 8080Started ApplicationName in 8 seconds 日志之前的启动前看到了这些语句
  • 处理器/写入器中的打印语句位于当您点击 url 时实际启动作业时将执行的代码中(即 processwrite 方法)。您在 reader bean 定义方法中放入的 print 语句只会在创建单例 bean itemReader 时在配置时打印。如果您在处理器/写入器上删除 @Component 并使用这些 bean 定义方法中的打印语句为它们创建 bean 定义方法,您将在配置时看到它们,就像阅读器一样。
  • 注明。谢谢。我刚刚看了你的视频“高性能批处理”。你的工作的忠实粉丝。另外,你能看看我的另一个问题吗? stackoverflow.com/questions/64094079/…
  • 谢谢!我会尽力帮助解决另一个问题。
猜你喜欢
  • 2015-07-30
  • 2014-06-20
  • 1970-01-01
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
相关资源
最近更新 更多