【问题标题】:Spring boot return a response from callback in servicesSpring Boot 从服务中的回调返回响应
【发布时间】:2020-07-11 18:50:24
【问题描述】:

我正在尝试使用 Spring boot 开发示例 Rest API 应用程序来测试我的 java 客户端库(这是 JS 客户端的转换)。 Java 客户端执行一些异步任务并以回调的形式返回响应。

这是我如何从示例应用程序的服务中调用它的示例。

@Async
public void initializeUser(InitRequest initRequest) {

    String BASE_URL = "http://sample_url";

    client.initUser(BASE_URL, initRequest, new ResponseCallback<InitRequest>() {

        @Override
        public void onSuccess(@NonNull InitRequest arg0) {
            // Return arg0 to controller
            System.out.println("User Initialized: " + arg0.getId());
        }

        @Override
        public void onError(@NonNull ResponseBody error) { 
            // Return error to controller
            System.out.println("User Initialize failed");
        }

        @Override
        public void validationError(@NonNull String arg0) {
             // return validationError to controller
            // TODO Auto-generated method stub

        }
    });
}

这里的 initUser 是在我的客户端中实现的方法。当我从我的控制器调用此方法时。控制器在实际请求完成之前返回,我无法在邮递员中看到任何响应。

这是一个控制器方法。

@RequestMapping(method=RequestMethod.POST, value = "/init" )
public void initUser( @RequestBody InitRequest initRequest) {
    experimentServices.initializeUser(initRequest);
    // wait for request to finish and send response to user
}

就像在 javascript 中一样,我可以使用 promises 或 async/await 来等待服务给出响应,然后再返回给用户。

我想知道.....

1) 如何在 Java 中实现类似的功能? (服务将一些数据返回给控制器,然后作为对最终用户的响应)。

2) Java 方法需要特定的返回响应,而服务可能会给出错误、验证错误或成功响应对象。有没有办法在一个函数中正确处理所有这些?

任何链接或文档都会有所帮助。 谢谢

【问题讨论】:

    标签: java spring spring-boot spring-rest


    【解决方案1】:

    在您的代码中,您异步调用的方法是 void 方法,这意味着它不会返回任何内容。在 Spring 中,使用 @Async 注释 bean 的方法将使其在单独的线程中执行,即调用者不会等待被调用方法的完成。

    所以,如果你想让控制器等到执行完成,如果你想等待结果我建议你使用Future。您可以采用将实际返回值包装在 Future 实例中的方法。我没有尝试编译此代码,但如下所示:

    @Async
    public Future<T> initializeUser(InitRequest initRequest) {
    
        String BASE_URL = "http://sample_url";
    
        client.initUser(BASE_URL, initRequest, new ResponseCallback<InitRequest>() {
    
            @Override
            public void onSuccess(@NonNull InitRequest arg0) {
                return new AsyncResult<InitRequest>(arg0);
                System.out.println("User Initialized: " + arg0.getId());
            }
    
            @Override
            public void onError(@NonNull ResponseBody error) { 
                return new AsyncResult<ResponseBody>(error);
                System.out.println("User Initialize failed");
            }
    
            @Override
            public void validationError(@NonNull String arg0) {
                 return new AsyncResult<String>(arg0);
                // TODO Auto-generated method stub
    
            }
        });
    }
    

    并在其余控制器中接收这个:

    @RequestMapping(method=RequestMethod.POST, value = "/init" )
    public InitRequest initUser( @RequestBody InitRequest initRequest) {
      Future<T> futureResult = experimentServices.initializeUser(initRequest);
      // wait for request to finish and send response to user
      if (futureResult.isDone()) {
          return futureResult.get();
      }
    }
    

    【讨论】:

    • 关于如何使用 Future 的任何示例链接?我看到了 FutureComplete 之类的东西。
    • 为此,我必须更改 JAVA 客户端方法 public void onSuccess 以返回 Future 实例而不是 void 对吗?
    • @DhavalP 如果您返回 void ,则意味着您没有向控制器返回任何结果。如果您希望控制器等待结果,那么您应该更改它。
    【解决方案2】:

    最好的办法是避免服务器忙于等待,所以使用 DeferredResult:

    private ExecutorService executor = ....
    
    @RequestMapping(method=RequestMethod.POST, value = "/init" )
    public DeferredResult<ResponseEntity<InitResponse>> initUser(@RequestBody InitRequest initRequest) {
        final DeferredResult<ResponseEntity<InitResponse>> output = new DeferredResult<>(5000L, 5000L);
        executor.submit(() -> {
            InitResponse response = processAndcreateRespnse(...);
            output.setResult(new ResponseEntity<>(response, HttpStatus.OK));
        });
    
        return output;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 2017-07-25
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 2020-10-07
      相关资源
      最近更新 更多