有时候我们的一个页面请求会执行很长时间,比如 10000 条数据的对比,假设需要花费3分钟,那么在这3分钟内该请求会一直占用着线程,如果这个时候只有一个线程,那么在这3分钟里所有页面都无法正常访问。异步 HTTP 请求就是为了解决这个问题。它会暂停当前的请求,等到执行完成后再返回结果。
1、新建一个有返回值的 Job 类
新建 Job 类用于执行耗时很长的操作。
package job;
import models.finance.BalanceReportModel;
import play.Logger;
import play.db.jpa.Transactional;
import play.jobs.Job;
import util.BalanceUtil;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 13-11-11
* Time: 下午7:15
* 访问记录统计任务
*/
public class BalanceJob extends Job<BalanceReportModel> {
String period = null;
public BalanceJob() {
}
public BalanceJob(String period) {
this.period = period;
}
@Override
@Transactional(readOnly = true)
public BalanceReportModel doJobWithResult() throws Exception {
BalanceReportModel retval = null;
try {
if (period != null) {
Logger.info("-------------BalanceJob Begin");
// 执行耗时很长的方法
retval = BalanceUtil.excute(period);
Logger.info("-------------BalanceJob End");
}
} catch (Exception e) {
Logger.error(e, "error in BalanceJob");
}
return retval;
}
}
2、在控制器的 Action 里异步执行 Job
使用 Promise 类执行异步操作,并使用 await() 方法等待返回结果。
package controllers.finance;
import job.BalanceJob;
import models.finance.BalanceReportModel;
import play.libs.F;
import play.mvc.Controller;
public class BalanceReport extends Controller {
public static void save(String period) {
if (period != null) {
try {
F.Promise<BalanceReportModel> delayedResult = new BalanceJob(period).now();
// 等待处理完成的结果
BalanceReportModel report = await(delayedResult);
if(report != null) {
flash.success(period + " 对账完成。" + report.summary);
}
} catch (Exception e) {
flash.error(e.getMessage() == null ? e.toString() : e.getMessage());
}
} else {
flash.error("请选择年月。");
}
render();
}
}