我有一个spring mvc web,我想执行一些表的更新。当我点击链接时,我必须等待任务完成才能执行另一项任务。每个链接对应不同的表,如果我想加快进程,我将如何改进。
控制器类
public class AdminController{
@Autowired
public SessionFactory sessionFactory;
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired
public HashMap<Long, ICollector> collectors;
@RequestMapping(value = "/config/configcollectlist",method = RequestMethod.GET)
public String getConfigCollectist(ModelMap model)
{
Session session = sessionFactory.openSession();
List<DbConfigCollect> configCollects = (List<DbConfigCollect>)session.createCriteria(DbConfigCollect.class).list();
session.close();
model.addAttribute("configCollects", configCollects);
return "admin/config/configcollectlist";
}
@RequestMapping(value = "/config/configcollectorlist",method = RequestMethod.GET)
public String getConfigCollectorist(ModelMap model)
{
Session session = sessionFactory.openSession();
List<DbConfigCollector> configCollectors = (List<DbConfigCollector>)session.createCriteria(DbConfigCollector.class).list();
session.close();
model.addAttribute("configCollectors", configCollectors);
return "admin/config/configcollectorlist";
}
}
任务类
public class CollectorPropertyRED_UK_PPD implements ICollector{
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired
public SessionFactory sessionFactory;
@Override
public void collect(DbConfigCollect inDbConfigCollect)
{
taskExecutor.execute(new CollectorPropertyRED_UK_PPDTask(sessionFactory, inDbConfigCollect));
}
}
public class CollectorPropertyRED_UK_PPDTask extends CollectorTaskBase {
public enum COLLECT_PARAMETER_PAPER_COREACUK_FILE {
FILE_INPUT,
};
public final static String FILE_SUFFIX_CSV = ".csv";
public CollectorPropertyRED_UK_PPDTask(SessionFactory sessionFactory,
DbConfigCollect inDbConfigCollect) {
super(sessionFactory, inDbConfigCollect);
}
public void run() {
String[] parameters = this.myDbConfigCollect.getParameters().split(";");
// load file
File[] sourceFiles = new File(
parameters[COLLECT_PARAMETER_PAPER_COREACUK_FILE.FILE_INPUT
.ordinal()]).listFiles();
int totalCount = 0;
for (int i = 0; i < sourceFiles.length; i++) {
if (sourceFiles[i].getName().endsWith(FILE_SUFFIX_CSV)) {
String timeStamp = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
String fileName = sourceFiles[i].getName();
CSVReader reader = null;
int count = 0;
try {
reader = new CSVReader(new FileReader(sourceFiles[i]));
String[] currLine = null;
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm");
while ((currLine = reader.readNext()) != null) {
String unique_id = currLine[0];
++count;
updateToDb(sessionFactory,currLine);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
}
}
}
}
}
}
}
更新: 我试图遵循async request guide,但它不会按预期工作。当我使用相同的URL刷新浏览器时,我立即得到控制器的响应,但是doSlowWork()方法需要等到上一个任务完成。这是我的代码。
控制器类
@Autowired
HelloService helloService;
Logger logger = LoggerFactory.getLogger(AdminController.class);
@RequestMapping(value ="/helloAsync", method = RequestMethod.GET)
public Callable<String> sayHelloAsync() {
System.out.println("Entering controller");
Callable<String> asyncTask = new Callable<String>() {
@Override
public String call() throws Exception {
return helloService.doSlowWork();
}
};
return asyncTask;
}
asynctask class
@Service
public class HelloService {
Logger logger = LoggerFactory.getLogger(HelloService.class);
public String doSlowWork() {
Random rand = new Random();
int n = rand.nextInt(50) + 1;
System.out.println("start: "+n);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end: "+ n);
return "index"; // return view's name
}
}
输出
INFO 2016-11-16 15:49:37,706 [http-bio-8080-exec-16] com.exbidata.db.mvc.controller.admin.AdminController - Entering controller
INFO 2016-11-16 15:49:37,710 [http-bio-8080-exec-16] com.exbidata.db.mvc.controller.admin.AdminController - Leaving controller
INFO 2016-11-16 15:49:37,720 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - Start slow work
INFO 2016-11-16 15:49:38,201 [http-bio-8080-exec-13] com.exbidata.db.mvc.controller.admin.AdminController - Entering controller
INFO 2016-11-16 15:49:38,202 [http-bio-8080-exec-13] com.exbidata.db.mvc.controller.admin.AdminController - Leaving controller
INFO 2016-11-16 15:49:38,975 [http-bio-8080-exec-15] com.exbidata.db.mvc.controller.admin.AdminController - Entering controller
INFO 2016-11-16 15:49:38,976 [http-bio-8080-exec-15] com.exbidata.db.mvc.controller.admin.AdminController - Leaving controller
INFO 2016-11-16 15:49:47,721 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - finish slow work
INFO 2016-11-16 15:49:47,723 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - Start slow work
INFO 2016-11-16 15:49:57,724 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - finish slow work
INFO 2016-11-16 15:49:57,726 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - Start slow work
INFO 2016-11-16 15:50:07,726 [taskExecutor-1] com.exbidata.db.mvc.controller.admin.HelloService - finish slow work
答案 0 :(得分:1)
您应该使用Spring异步请求处理功能,
使用Servlet 3.0,添加了异步支持。首先,您需要在web.xml中启用异步支持,如下所示,
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet- class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- turn on async support for servlet -->
<async-supported>true</async-supported>
</servlet>
从现有的控制器处理程序方法而不是返回字符串返回可调用
@RequestMapping(value = "/config/configcollectlist",method = RequestMethod.GET)
public Callable<String> getConfigCollectist(ModelMap model)
{
Callable<String> asyncTask = new Callable<String>() {
@Override
public String call() throws Exception {
Session session = sessionFactory.openSession();
List<DbConfigCollect> configCollects = (List<DbConfigCollect>)session.createCriteria(DbConfigCollect.class).list();
session.close();
model.addAttribute("configCollects", configCollects);
return "admin/config/configcollectlist";
}
};
return asyncTask;
}
此外,您还需要为异步支持配置spring应用程序上下文。 (我已经提到了基于XML的配置)
<mvc:annotation-driven>
<mvc:async-support default-timeout="30000" task-executor="taskExecutor"/>
</mvc:annotation-driven>
<!-- modify the parameters of thread pool -->
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5"/>
<property name="maxPoolSize" value="50"/>
<property name="queueCapacity" value="10"/>
<property name="keepAliveSeconds" value="120"/>
</bean>