在springmvc中如果通过http请求触发的一个耗时任务,想使用异步执行的方式,使用传统的new Thread是无法实现的。会话超时或者返回后,异步的线程也会消亡。
支持的版本是2.0.3以后,3.2后基于servlet3.0可通过可通过返回 Callable 来完成异步处理。
package controller;
import domain.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
/**
* 系统配置的操作
*
* @author wq
* @since 14-4-23 下午4:50
*/
@Controller
@RequestMapping(value = {"", "/index"})
public class IndexController {
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
@Resource
private DataProducer dataProducer;
@RequestMapping(value = "", method = RequestMethod.GET)
public String index() {
return "index";
}
@RequestMapping(value = {"/beginTest"}, method = RequestMethod.POST)
@ResponseBody
public Response beginTest() {
Response resp = new Response();
resp.setStatus(Response.FAILURE);
try {
AsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("bp");
Future<Map<String, String>> future = executor.submit(new OutThread());
resp.setStatus(Response.SUCCESS);
resp.setData(future.get());
} catch (RuntimeException ex) {
logger.error("运行异常", ex);
resp.setMsg(ex.getMessage());
} catch (Exception e) {
resp.setMsg("内部错误");
logger.error("执行失败", e);
}
return resp;
}
class OutThread implements Callable<Map<String, String>> {
@Override
public Map<String, String> call() throws Exception {
return dataProducer.start();
}
}
}
在dataProducer.start();这个方法内部可以使用多线程加速任务执行过程。