2012-02-02 113 views
4

我有一個Spring-Batch作業,我從Spring MVC控制器啓動。該控制器從用戶獲取上傳的文件和作業應該處理文件:Spring批處理:從Spring MVC控制器啓動一個作業WITH NEW THREAD

@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實現這一點?

回答

6

官方documentation說明您的具體問題,並在4.5.2. Running Jobs from within a Web Container一個解決方案:

[...]控制器啓動使用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="jobRepository" ref="jobRepository" /> 
    <property name="taskExecutor" ref="taskExecutor"/> 
</bean> 

免責聲明:我從來沒有使用過春節批...

+0

謝謝!正是我想要的!初學者的運氣:) – rapt 2012-02-02 15:32:48

+0

第二個鏈接是404,請更新正確的鏈接。 – Rembo 2015-01-13 07:37:43

1

如果您不需要向客戶端顯示處理錯誤,則可以在單獨的線程中啓動彈簧批處理作業。

+0

我在想它 - 但是在春季批量框架中是否有這樣的設置?例如。假設我希望每個請求都爲它的作業啓動一個新線程,但最多隻能有10個這樣的線程 - 如果我現在有超過10個文件需要處理,那麼只有10個文件會獲得他們自己的新線程和其他文件將稍後處理,也許由一些全球調度程序處理。 Spring-batch開發人員是否已經實施(至少部分)? – rapt 2012-02-02 14:56:07

3

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類中使用它。

相關問題