Spring Batch:以新的思路从Spring MVC控制器中开始工作
问题内容:
我有一个从Spring MVC控制器启动的Spring-Batch作业。控制器从用户那里获取一个上传的文件,并且作业应该处理该文件:
@RequestMapping(value = "/upload")
public ModelAndView uploadInventory(UploadFile uploadFile, BindingResult bindingResult) {
// code for saving the uploaded file to disk goes here...
// now I want to launch the job of reading the file line by line and saving it to the database,
// but I want to launch this job in a new thread, not in the HTTP request thread,
// since I so not want the user to wait until the job ends.
jobLauncher.run(
jobRegistry.getJob(JOB_NAME),
new JobParametersBuilder().addString("targetDirectory", folderPath).addString("targetFile", fileName).toJobParameters()
);
return mav;
}
我尝试了以下XML配置:
<job id="writeProductsJob" xmlns="http://www.springframework.org/schema/batch">
<step id="readWrite">
<tasklet task-executor="taskExecutor">
<chunk reader="productItemReader" writer="productItemWriter" commit-interval="10" />
</tasklet>
</step>
</job>
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="5" />
</bean>
…但是似乎多线程仅发生在作业边界本身内。即,控制器线程等待直到作业结束,并且作业执行由多个线程处理(这很好,但不是我想要的主要内容)。我想要的主要事情是作业将在一个或多个单独的线程上启动,而控制器线程将继续执行,而无需等待作业线程结束。
有没有办法用Spring-batch实现这一目标?
问题答案:
官方文档在4.5.2中描述了您的确切问题和解决方案。从Web容器中运行作业:
[…]控制器使用
JobLauncher
已配置为异步启动的来启动Job
,它立即返回JobExecution
。Job可能仍会运行,但是,这种非阻塞行为 允许控制器立即返回
,这在处理HttpRequest时是必需的。
Spring Batch http://static.springsource.org/spring-batch/reference/html-
single/images/launch-from-request.png
因此,您在尝试使用时非常接近TaskExecutor
,但是需要将其传递给JobLauncher
:
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor" ref="taskExecutor"/>
</bean>
免责声明: 我从未使用过Spring Batch …