Return OkHttp异步结果有问题

Return OkHttp Asynchronous result has some problem

我有一个 java SDK,它使用 OkHttp 客户端(4.0.0)从 IAM server and return token to application.The relation may like this:Applicaiton Sync call SDKSDK Async call IAM.Refer to this answer, 代码如:

异步Class:

class BaseAsyncResult<T> {
private final CompletableFuture<T> future = new CompletableFuture<>();

T getResult() {
    try {
        return future.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    return null;
}

void onFailure(IOException e) {
    future.completeExceptionally(e);
}

void onResponse(Response response) throws IOException {
    String bodyString = Objects.requireNonNull(response.body()).string();
    future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));
}
}

Okhttp 调用如下:

public void invoke(Request request, BaseAsyncResult result) {
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                result.onFailure(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                result.onResponse(response);
            }
        });
    }

应用程序使用 sdk 代码,iasClient 是 okhttp 客户端的包装器:

 BaseAsyncResult<AuthenticationResponse> iasAsyncResult = new BaseAsyncResult();
 iasClient.invoke(request, iasAsyncResult);
 AuthenticationResponse result = iasAsyncResult.getResult();

错误信息:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to x.x.x.AuthenticationResponse

我错过了什么?

您需要确保 jackson 知道哪个 class 将值反序列化为 。在这种情况下,您要求 Jackson 将响应反序列化为 TypeReference ,默认情况下它将解析为 Map 除非您指定 class (在本例中为 AuthenticationResponse )。因此,Future 解析为 linkedHashMap 并导致 class 强制转换。 尝试替换下面的行。

future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));

future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<AuthenticationResponse>() {}));

@Arpan Kanthal 的一种方法是向 BaseAsyncResult 添加一个私有 Class 类型变量,然后在您的 json2Pojo 函数中使用该 class,然后 BaseAsyncResult 可能如下所示:

public class BaseAsyncResult<T> {
    private final CompletableFuture<T> future = new CompletableFuture<>();
    private Class<T> classType;

    public BaseAsyncResult(Class<T> classType) {
        this.classType = classType;
    }

    public T getResult() {
        try {
            return future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }

    void onFailure(IOException e) {
        future.completeExceptionally(e);
    }

    void onResponse(Response response) throws IOException {
        future.complete(JacksonUtil.json2Pojo(response.body().string(), classType));
    }
}