Spring Batch:从一个带有新线程的Spring MVC控制器中启动一个作业 [英] Spring Batch: starting a job from within a Spring MVC contorller WITH A NEW THREAD

查看:182
本文介绍了Spring Batch:从一个带有新线程的Spring MVC控制器中启动一个作业的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring-Batch作业,我是从Spring MVC控制器启动的。控制器从用户获取上传文件,作业应该处理文件:

  @RequestMapping(value =/上传)
public ModelAndView uploadInventory(UploadFile uploadFile,BindingResult bindingResult){

//将上传的文件保存到磁盘的代码在这里...

/ /现在我想启动逐行读取文件并将其保存到数据库的工作,
//但我想在新线程中启动此作业,而不是在HTTP请求线程中,
//因为我不希望用户等到作业结束。
jobLauncher.run(
jobRegistry.getJob(JOB_NAME),
new JobParametersBuilder()。addString(targetDirectory,folderPath).addString(targetFile,fileName).toJobParameters()
);

返回mav;
}

我尝试过以下XML配置:

 < job id =writeProductsJobxmlns =http://www.springframework.org/schema/batch> 
< step id =readWrite>
< tasklet task-executor =taskExecutor>
< chunk reader =productItemReaderwriter =productItemWritercommit-interval =10/>
< / tasklet>
< / step>
< / job>

< bean id =taskExecutor
class =org.springframework.scheduling.concurrent.ThreadPoolTask​​Executor>
< property name =corePoolSizevalue =5/>
< property name =maxPoolSizevalue =5/>
< / bean>

...但似乎多线程只在作业边界内发生。即,控制器线程等待直到作业结束,并且作业执行由多个线程处理(这很好,但不是我想要的主要内容)。我想要的主要是该作业将在一个单独的线程(或线程)上启动,而控制器线程将继续执行而不等待作业线程结束。



<有没有办法用Spring批处理实现这个目的?

解决方案

官方文档描述了您的确切问题以及 4.5.2。从Web容器中运行作业


[...]控制器使用 <启动作业已配置为异步启动的code> JobLauncher ,会立即返回 JobExecution 。作业可能仍在运行,但是,这种非阻塞行为允许控制器立即返回,这在处理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 =jobRepositoryref =jobRepository/>
< property name =taskExecutorref =taskExecutor/>
< / bean>

免责声明:我从未使用过Spring Batch ...


I have a Spring-Batch job that I launch from a Spring MVC controller. The controller gets an uploaded file from the user and the job is supposed to process the file:

@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;
}

I've tried the following XML config:

<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>

...but it seems like the multithreading happens only within the job boundaries itself. I.e., the controller thread waits until the job ends, and the job execution is handled by multiple threads (which is good but not the main thing I wanted). The main thing I wanted is that the job will be launched on a separate thread (or threads) while the controller thread will continue its execution without waiting for the job threads to end.

Is there a way to achieve this with Spring-batch?

解决方案

The official documentation describes your exact problem and a solution in 4.5.2. Running Jobs from within a Web Container:

[...] The controller launches a Job using a JobLauncher that has been configured to launch asynchronously, which immediately returns a JobExecution. The Job will likely still be running, however, this nonblocking behaviour allows the controller to return immediately, which is required when handling an HttpRequest.

Spring Batch http://static.springsource.org/spring-batch/reference/html-single/images/launch-from-request.png

So you were pretty close in trying to use TaskExecutor, however it needs to be passed to the JobLauncher instead:

<bean id="jobLauncher"
      class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
    <property name="taskExecutor" ref="taskExecutor"/>
</bean>

Disclaimer: I have never used Spring Batch...

这篇关于Spring Batch:从一个带有新线程的Spring MVC控制器中启动一个作业的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆