Spring Batch:从一个带有新线程的Spring MVC控制器中启动一个作业
我有一个Spring-Batch作业,我从Spring MVC控制器启动。 控制器从用户获取上传的文件,该作业应该处理该文件:
@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配置:
…但似乎multithreading仅在作业边界内发生。 即,控制器线程等待直到作业结束,并且作业执行由多个线程处理(这是好的但不是我想要的主要内容)。 我想要的主要是作业将在一个单独的线程(或线程)上启动,而控制器线程将继续执行而不等待作业线程结束。
有没有办法用Spring-batch实现这个目标?
官方文档描述了您的确切问题以及4.5.2中的解决方案。 从Web容器中运行作业 :
[…]控制器使用已配置为异步启动的
JobLauncher
启动作业,该作业立即返回JobExecution
。 作业可能仍在运行,但是,这种非阻塞行为允许控制器立即返回 ,这在处理HttpRequest时是必需的。
Spring Batch http://sofzh.miximages.com/java/launch-from-request.png
所以你非常接近尝试使用TaskExecutor
,但是它需要传递给JobLauncher
:
免责声明:我从未使用过Spring Batch …
jobLauncher.run()
方法可以在新的Thread
调用,如下所示:
@RequestMapping(value = "/upload") public ModelAndView uploadInventory(UploadFile uploadFile, BindingResult bindingResult) { [...] final SomeObject jobLauncher = [...] Thread thread = new Thread(){ @Override public void run(){ jobLauncher.run([...]); } }; thread.start(); return mav; }
thread.start()
行将生成一个新线程,然后继续执行它下面的代码。
请注意,如果jobLauncher
是局部变量,则必须将其声明为final
,以便在匿名Thread
类中使用它。
如果您不需要向客户端显示处理错误,则可以在单独的线程中启动spring批处理作业。