【问题标题】:Intercept return async call Spring拦截返回异步调用 Spring
【发布时间】:2018-09-08 08:32:00
【问题描述】:

我想要一些关于如何在 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 错误 [stderr] (pool-15-thread-2) 线程“pool-15-thread-2”中的异常 java.lang.NullPointerException eu.sia.pda.pdaportal.web.controller.CustomController$2.onSuccess(CustomController.java:169) 的 16:02:00,626 错误 [stderr] (pool-15-thread-2) 16:02:00,626 错误 [stderr] (pool-15-thread-2) 在 eu.sia.pda.pdaportal.web.controller.CustomController$2.onSuccess(CustomController.java:161) 16:02:00,626 错误 [stderr] (pool-15-thread-2) 在 com.google.common.util.concurrent.Futures$6.run(Futures.java:1773) 16:02:00,626 错误 [stderr] (pool-15-thread-2) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 16:02:00,626 错误 [stderr] (pool-15-thread-2) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 16:02:00,626 错误 [stderr] (pool-15-thread-2) at java.lang.Thread.run(Thread.java:748)

为什么??

【问题讨论】:

    标签: java spring-boot asynchronous reverse-proxy interceptor


    【解决方案1】:

    请注意,如果您只是这样做:

    Future<Long> future = methodAsync(key);
    

    然后return 您无法从异步方法中检索结果,因为您不再引用您的 future(它将被垃圾收集)

    您需要有机制(后端线程)能够在异步方法可用时读取结果。

    即使使用单独的后端线程来“收集”异步响应,您仍然有另一个问题要解决如何将其与客户端通信 - 以及与哪个客户端通信。

    假设您控制客户端,您可以强制它汇集结果(在不同端点上)并在此类结果可用时显示警报,或者使用服务器推送技术,例如:https://developers.google.com/web/fundamentals/codelabs/push-notifications/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多