领导说,我们不能绑定在某个产品,某个框架,某个技术实现上。所以当我们希望使用 jetty 的 continuation 技术的时候,我们必须对它进行一个包装,以保证将来如果需要,我们可以用其它的技术或框架进行替换。
一个简单的包装:
TaskManager 类:
/**
* submit a task async
*
* @param request
* @param response
* @param task
* @return result true for first submit task, false for expire or exception
*/
public static boolean submitTask(final HttpServletRequest request,
final HttpServletResponse response,
final AbstractContinuation task) {
final Continuation continuation = ContinuationSupport
.getContinuation(request);
if (continuation.isExpired()) {
@SuppressWarnings("unchecked")
final FutureTask ftask = (FutureTask) request
.getAttribute(TASK_FUTURE);
if (ftask != null) {
// not Interrupt if it is still running
ftask.cancel(false);
}
task.onExpire(request, response);
return false;
}
// first call of this request
continuation.setTimeout(ContinuationConfig.timeout);
continuation.suspend(response);
try {
final FutureTask ftask = new FutureTask(task) {
@Override
protected void done() {
// cancelled, just return
if (isCancelled()) {
return;
}
// expired, just return
if (continuation.isExpired()) {
return;
}
// complete, so *NO* attribute will take effects
// request.setAttribute(TASK_RESULTS, get());
try {
final Object result = get();
task.onResult(request, response, result);
} catch (final Exception e) {
task.onException(request, response, e);
}
continuation.complete();
}
};
exec.submit(ftask);
request.setAttribute(TASK_FUTURE, ftask);
return true;
} catch (final TooManyWaitingTaskException e) {
task.onException(request, response, e);
return false;
}
}
/**
* submit a task sync, with *NO* expire support
*
* @param request
* @param response
* @param task
* @return result true for first submit task, false for expire or exception
*/
public static boolean submitTask2(final HttpServletRequest request,
final HttpServletResponse response,
final AbstractContinuation task) {
try {
final Object result = task.call();
task.onResult(request, response, result);
return true;
} catch (final TooManyWaitingTaskException e) {
task.onException(request, response, e);
return false;
} catch (final Exception e) {
task.onException(request, response, e);
return false;
}
}
servlet 里面可以这样调用:(注意,当前不支持 jsp )
@Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
// create an asynchronous task
final AbstractContinuation task = new AbstractContinuation() {
@Override
public Object call() throws Exception {
// do the job
}
@Override
public void onResult(final HttpServletRequest request,
final HttpServletResponse response, final Object result) {
// has result, so ignore all exception
// do output
}
@Override
public void onExpire(final HttpServletRequest request,
final HttpServletResponse response) {
try {
response.sendError(504, "continuation job expired");
log.warn("on expire:" + request);
} catch (final IOException e) {
log.warn("exception on expire: " + request + e.getMessage());
}
return;
}
@Override
public void onException(final HttpServletRequest request,
final HttpServletResponse response, final Exception e) {
try {
response.sendError(503, "some exception occured ");
log.warn("on exception:" + request, e);
} catch (final IOException ioe) {
log.warn("exception on exception: " + request
+ e.getMessage() + ioe.getMessage());
}
return;
}
};
if (TaskManager.submitTask(request, response, task)) {
// first submit
// do nothing here
} else {
// expire, or exception
// just ignore here, because we have dealed with it other place
}
return;
}