Spring Batch是否适合我的服务代码?

时间:2017-04-27 22:34:23

标签: java spring spring-batch

从高层次来看,我的申请流程似乎是

REST控制器RequestMapping由GET()请求触发。 REST控制器调用Service类中的方法。

@RequestMapping(value="/eventreports", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody List<EventReports> addReportIds(@RequestBody List<Integer> reportIds) {
    List<EventReports> eventReports = railAgentCollectorServiceImpl.addReportIds(reportIds);
    return eventReports;

}

服务方法在DAO类中调用方法。

@Override
public List<EventReports> addReportIds(List<Integer> reportIds) {

    List<EventReports> eventReports = eventReportsDAOImpl.listEventReportsInJsonRequest(reportIds);
    return eventReports;
}

DAO方法针对SQL数据源执行StoredProcedureQuery,该数据源将结果作为域对象的ArrayList返回。 Service类将域对象的Arraylist传递回REST Controller,REST Controller将域对象的ArrayList作为JSON字符串返回。

@Override
public List<EventReports> listEventReportsInJsonRequest(List<Integer> reportIds) {

    ArrayList<EventReports> erArr = new ArrayList<EventReports>();
    try {
        StoredProcedureQuery q = em.createStoredProcedureQuery("sp_get_event_reports", "eventReportsResult");
        q.registerStoredProcedureParameter("reportIds", String.class, ParameterMode.IN);
        q.setParameter("reportIds", reportIdsList);
        boolean isResultSet = q.execute(); //try catch here
        erArr = (ArrayList<EventReports>) q.getResultList();
    } catch (Exception e) {
        System.out.println("No event reports found for list " + reportIdsList);
    }

    return erArr;
}

我一直在研究将Spring Batch处理集成到上面的模式中。我一直在寻找批量处理的Spring入门指南https://spring.io/guides/gs/batch-processing/ - 特别注意BatchConfiguration.java的源代码 - 我不确定我的应用程序是否适合Spring Batch,也许我不完整的知识Spring Batch及其实现的各种方式阻碍了我对它的概念化。下面的BatchConfiguration.java代码告诉我,Spring Batch可能最适合迭代项目列表,逐个读取它们,逐个处理它们,然后逐个编写它们 - 而我的服务代码基于一次收集和写入对象列表。

@Bean
public FlatFileItemReader<Person> reader() {
    FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
    reader.setResource(new ClassPathResource("sample-data.csv"));
    reader.setLineMapper(new DefaultLineMapper<Person>() {{
        setLineTokenizer(new DelimitedLineTokenizer() {{
            setNames(new String[] { "firstName", "lastName" });
        }});
        setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
            setTargetType(Person.class);
        }});
    }});
    return reader;
}

@Bean
public PersonItemProcessor processor() {
    return new PersonItemProcessor();
}

@Bean
public JdbcBatchItemWriter<Person> writer() {
    JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
    writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
    writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
    writer.setDataSource(dataSource);
    return writer;
}
// end::readerwriterprocessor[]

// tag::jobstep[]
@Bean
public Job importUserJob(JobCompletionNotificationListener listener) {
    return jobBuilderFactory.get("importUserJob")
            .incrementer(new RunIdIncrementer())
            .listener(listener)
            .flow(step1())
            .end()
            .build();
}

@Bean
public Step step1() {
    return stepBuilderFactory.get("step1")
            .<Person, Person> chunk(10)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
}

这是真的吗?我还能利用Spring Batch为现有代码提供的恢复能力,调度和同步吗?任何建议表示赞赏。

2 个答案:

答案 0 :(得分:0)

我认为您需要考虑这种同步行为和异步行为。批处理过程用于长时间运行的任务,所以,

考虑你的任务是否长期运行。如果您的任务长时间运行,您可以使用批处理。这将是异步的,因为您的请求进入并启动任务,然后回复给用户。

批处理将运行并完成并将结果写回数据库,用户必须使用ajax轮询结果,或者您可能必须实现推送通知机制来处理异步行为的任务状态/阻止民意调查。

答案 1 :(得分:0)

真正的是一个由读者组成的Spring Batch块 - &gt;处理器 - &gt;编写者读取一个项目,处理一个项目,但根据定义的块大小写入一大块项目

因此,根据您定义的 chunk_size ,您可以一次性发送数千个项目给作者写入存储空间。

话虽如此,读者只读了一个项目,但没有必要从源(从文件/数据库等)本身只读取一个项目。有些读者可以从源头一次读取大量的项目,将其自身保存在列表中并逐个移交给处理器,直到列表用完为止。

其中一个读者是JdbcPagingItemReader,例如它按照定义的阅读器一次从数据库读取几千行 page_size (显着减少了DB调用),然后一个接一个地交给处理器,然后处理器自动保持累积处理后的输出直到 chunk_size ,然后批量交给作家。

它只是另一种情况,即你的API中的要求可能没有现成的东西 - 在这种情况下,你必须编写自己的ItemReader

查看JdbcPagingItemReader的代码以获取想法。

对于你的情况,Spring Batch的编写者根本不是一个问题,它只是通过简单的配置批量编写。您必须将Controller的输出提供给阅读器,阅读器的作用与JdbcPagingItemReader类似。

我只想说内存处理是一个接一个(而且速度非常快),但IO可以在春季批量中批量完成(如果你选择的话)。

希望它有所帮助!!