You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java调用Firebase FCM HTTP v1 API时,通过OAuth2获取AccessToken出现NoSuchMethodError异常的问题

Java调用Firebase FCM HTTP v1 API时,通过OAuth2获取AccessToken出现NoSuchMethodError异常的问题

根据你描述的场景和报错信息,这个问题的核心是依赖版本冲突,具体是Guava(Google核心工具库)的版本不兼容导致的,下面是详细的分析和解决方案:

问题根源

java.lang.NoSuchMethodError: com.google.common.util.concurrent.Futures.getDone(...)这个异常,本质是运行时找不到Futures.getDone方法——这个方法是在Guava 20.0及以上版本才新增的。

你引入的firebase-admin:9.2.0本身依赖的是高版本的Guava,但你的项目中可能存在其他依赖,它们通过传递依赖引入了低于20.0的旧版Guava,导致运行时旧版Guava覆盖了新版,进而找不到这个方法。

解决方案

1. 定位冲突的Guava依赖

首先用Maven命令生成依赖树,找出所有引入Guava的依赖及其版本:

mvn dependency:tree | grep guava

执行后会输出类似这样的结果:

[INFO] +- com.google.guava:guava:jar:20.0:compile
[INFO] +- xxx:xxx:jar:1.0:compile
[INFO] |  \- com.google.guava:guava:jar:19.0:compile

找到其中版本低于20.0的条目,这就是冲突的来源。

2. 排除旧版Guava的传递依赖

对于引入旧版Guava的那个依赖,在pom.xml中添加exclusions,排除它的Guava传递依赖:

<dependency>
    <!-- 这里替换成你找到的引入旧版Guava的依赖坐标 -->
    <groupId>xxx</groupId>
    <artifactId>xxx</artifactId>
    <version>xxx</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>

3. 显式声明兼容的Guava版本

为了彻底避免冲突,可以直接在pom.xml中显式指定firebase-admin:9.2.0兼容的Guava版本(该版本兼容的Guava版本为31.1-jre):

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>

4. 验证并刷新依赖

执行以下命令清理并重新下载依赖,确保生效:

mvn clean install -U

再次执行mvn dependency:tree | grep guava,确认所有Guava的版本都是你指定的高版本。

代码优化建议

另外,你的getAccessToken方法可以做一点优化:把GoogleCredentials实例缓存起来,避免每次都读取本地文件和初始化,提升性能:

import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

public class FcmTokenUtils {
    private static final String MESSAGING_SCOPE = "https://www.googleapis.com/auth/firebase.messaging";
    private static final String[] SCOPES = {MESSAGING_SCOPE};
    // 缓存Credentials实例,避免重复初始化
    private static GoogleCredentials cachedCredentials;

    // 静态代码块初始化Credentials,只执行一次
    static {
        try {
            cachedCredentials = GoogleCredentials.fromStream(new FileInputStream("service.json"))
                    .createScoped(Arrays.asList(SCOPES));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("初始化Firebase凭证失败", e);
        }
    }

    private static String getAccessToken() throws IOException {
        cachedCredentials.refreshIfExpired();
        AccessToken token = cachedCredentials.getAccessToken();
        return token.getTokenValue();
    }
}

额外说明

如果你的IDE是IntelliJ IDEA,可以安装Maven Helper插件,它能更直观地展示依赖冲突,一键排除冲突依赖,操作更高效。

备注:内容来源于stack exchange,提问作者user2166934

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 07:45:27