JavaSpring-从异步回调返回?

JavaSpring-从异步回调返回?,java,spring,asynchronous,firebase,firebase-authentication,Java,Spring,Asynchronous,Firebase,Firebase Authentication,使用Spring(Java)和Firebase在后端工作。我们使用Firebase令牌(附加为身份验证标头)来标识用户,使用 不幸的是,从令牌中提取此UID必须异步完成,因此我只能从onSuccess回调中获取令牌。 为了提供响应,我必须从下面的deleteUser方法返回一个对象,但是在得到成功/失败回调之前,我无法知道响应是什么 我可以想象一种方法,通过等待回调中设置的标志来实现这一点,或者使用一些混乱的时间,但是我想知道是否有一种干净的方法来处理这个问题,而不引入竞争条件或大量额外的代码。

使用Spring(Java)和Firebase在后端工作。我们使用Firebase令牌(附加为身份验证标头)来标识用户,使用

不幸的是,从令牌中提取此UID必须异步完成,因此我只能从
onSuccess
回调中获取令牌。 为了提供响应,我必须从下面的
deleteUser
方法返回一个对象,但是在得到成功/失败回调之前,我无法知道响应是什么

我可以想象一种方法,通过等待回调中设置的标志来实现这一点,或者使用一些混乱的时间,但是我想知道是否有一种干净的方法来处理这个问题,而不引入竞争条件或大量额外的代码。有人能帮忙吗

请求映射(处理请求,服务响应)
@RequestMapping(value=“/users”,method=RequestMethod.DELETE)
public@ResponseBody字符串deleteUser(@RequestHeader(“身份验证”)字符串令牌){
FirebaseUtil.getUid(令牌,新的OnSuccessListener(){
@凌驾
成功时公共无效(FirebaseToken已解码){
字符串uid=decodedToken.getUid();
//在此返回成功
}
},新的OnFailureListener(){
@凌驾
public void onFailure(@NonNull异常e){
//此处返回失败
}
});
//你必须在这里还些东西吗?
User userToDelete=userDao.get(uid);//这里没有uid
userDao.delete(uid);
clearUserAccounts(userToDelete);
返回uid+“已删除”;
}
FirebaseUtil.getUid()
publicstaticvoidgetuid(字符串标记、OnSuccessListener成功监听器、OnFailureListener失败监听器){
FirebaseAuth.getInstance()
.verifyIdToken(令牌)
.addOnSuccessListener(successListener)
.addOnFailureListener(failureListener);
}

虽然有一些方法可以阻止线程直到异步请求完成,但自Spring 3.2以来,有一个简单且更有效的解决方案

您可以使用
DeferredResult
作为返回类型来启用异步处理。这允许servlet容器立即重用HTTP工作线程,同时省去了强制序列化异步请求链的麻烦

通过填写注释,您的代码如下所示:

@RequestMapping(value = "/users", method = RequestMethod.DELETE)
public DeferredResult<String> deleteUser(@RequestHeader("Authentication") String token) {
    final DeferredResult<String> result = new DeferredResult<>();

    FirebaseUtil.getUid(token, new OnSuccessListener<FirebaseToken>() {
        @Override
        public void onSuccess(FirebaseToken decodedToken) {
            String uid = decodedToken.getUid();
            User userToDelete = userDao.get(uid);
            userDao.delete(uid);
            clearUserAccounts(userToDelete);
            result.setResult(uid + " was deleted");
        }
    }, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            result.setErrorResult(e);
        }
    });

    return result;
}
@RequestMapping(value=“/users”,method=RequestMethod.DELETE)
public DeferredResult deleteUser(@RequestHeader(“身份验证”)字符串令牌){
最终递延结果=新递延结果();
FirebaseUtil.getUid(令牌,新的OnSuccessListener(){
@凌驾
成功时公共无效(FirebaseToken已解码){
字符串uid=decodedToken.getUid();
User userToDelete=userDao.get(uid);
userDao.delete(uid);
clearUserAccounts(userToDelete);
result.setResult(uid+“已删除”);
}
},新的OnFailureListener(){
@凌驾
public void onFailure(@NonNull异常e){
result.setErrorResult(e);
}
});
返回结果;
}

谢谢-我最近还发现了Callables,除了必须重写
call()
?它们会起作用吗?如果不会,原因是什么?很好的发现。正如博客文章所指出的,Callables是类似的,但它们并不适用于您的问题。Callable必须包装(可能是长时间运行的)同步请求,而Firebase方法是纯异步的。
public static void getUid(String token, OnSuccessListener<FirebaseToken> successListener, OnFailureListener failureListener) {
        FirebaseAuth.getInstance()
                .verifyIdToken(token)
                .addOnSuccessListener(successListener)
                .addOnFailureListener(failureListener);
    }
@RequestMapping(value = "/users", method = RequestMethod.DELETE)
public DeferredResult<String> deleteUser(@RequestHeader("Authentication") String token) {
    final DeferredResult<String> result = new DeferredResult<>();

    FirebaseUtil.getUid(token, new OnSuccessListener<FirebaseToken>() {
        @Override
        public void onSuccess(FirebaseToken decodedToken) {
            String uid = decodedToken.getUid();
            User userToDelete = userDao.get(uid);
            userDao.delete(uid);
            clearUserAccounts(userToDelete);
            result.setResult(uid + " was deleted");
        }
    }, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            result.setErrorResult(e);
        }
    });

    return result;
}