我想了解如何拦截Spring中异步方法的返回类型,以便向用户发出方法的结果。
我试着在技术上更好地解释:
在我的控制器类中,我启动了一个异步方法
@Controller
@RequestMapping(value = AppUtil.DEFAULT_ADMIN_URL + "/xxx")
@Slf4j
public class CustomController extends AbstractController {
...
RequestMapping(value = "/url", method = RequestMethod.POST)
public String confirm(@PathVariable(value = "key") String key, HttpServletRequest request, Locale locale, final RedirectAttributes redirectAttributes) {
...
Future<Long> future = methodAsync(key);
// here I go out because the call async is very long and I do not
// want to redeem that the reverse proxy I throw down the session
return "redirect:/admin/another-controller";
}
}
现在,我希望能够在结束时拦截方法的返回,并将其报告给用户,例如通过警报。
我怎么能这样做?提前致谢
编辑1:
查看此链接后:https://gist.github.com/bbejeck/1387892,我使用Futures.addCallback拦截异步方法的返回类型,现在我想,如果成功,则从Controller重定向到另一个页面,这样:
ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Long> future = pool.submit(() -> asyncMethod(key));
Futures.addCallback(future, new FutureCallback<Long>() {
@Override
public void onSuccess(Long result) {
log.info("Complete");
try {
// String urlWithSessionID = response.encodeRedirectURL("/xxx/controller/" + result);
// response.sendRedirect(urlWithSessionID);
RequestDispatcher rd = request.getRequestDispatcher("/xxx/controller/" + result);
rd.forward(request, response);
pool.shutdown();
} catch (IOException e) {
log.error("Exception in sendRedirect", e);
} catch (ServletException e) {
log.error("Exception in sendRedirect", e);
}
}
@Override
public void onFailure(Throwable t) {
log.error("Exception in task", t);
pool.shutdown();
}
});
我尝试使用重定向和转发功能,但在这两种情况下,我都会在信息日志之后出现此异常:
16:02:00,626 ERROR [stderr](pool-15-thread-2)线程“pool-15-thread-2”中的异常java.lang.NullPointerException 16:02:00,626 ERROR [stderr](pool-15-thread-2)at eu.sia.pda.pdaportal.web.controller.CustomController $ 2.onSuccess(CustomController.java:169) 16:02:00,626 ERROR [stderr](pool-15-thread-2)at eu.sia.pda.pdaportal.web.controller.CustomController $ 2.onSuccess(CustomController.java:161) 16:02:00,626 com.google.common.util.concurrent.Futures $ 6.run(Futures.java:1773)中的ERROR [stderr](pool-15-thread-2) 16:02:00,626 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)中的错误[stderr](pool-15-thread-2) 16:02:00,626 java.util.concurrent.ThreadPoolExecutor中的ERROR [stderr](pool-15-thread-2)$ Worker.run(ThreadPoolExecutor.java:624) 16:02:00,626 java.lang.Thread.run中的错误[stderr](pool-15-thread-2)(Thread.java:748)
为什么?
答案 0 :(得分:1)
请注意,如果您这样做:
Future<Long> future = methodAsync(key);
然后return
您无法从异步方法中检索结果,因为您不再引用future
(它将被垃圾收集)
你需要有一个机制(一个后端线程),当从异步方法可用时,它将能够读取结果。
即使有单独的后端线程,也会收集&#39;异步响应你仍然有另一个问题来解决如何将它传达给客户端 - 以及客户端。
假设您控制客户端,您可以强制它为结果汇集(在不同的端点上)并在此类结果可用时显示警报,或使用服务器推送技术,例如:https://developers.google.com/web/fundamentals/codelabs/push-notifications/