Servlet通过FCM发Android通知报错:FirebaseApp [DEFAULT]不存在
解决FCM发送通知时FirebaseApp [DEFAULT]不存在的问题
错误原因
Servlet运行在Java EE环境中,Firebase SDK不会自动初始化默认的FirebaseApp实例,直接调用FirebaseMessaging.getInstance()会因为找不到DEFAULT实例抛出异常。另外你原代码里同时设置了setTopic和setToken,这也是错误的——FCM消息只能指定一种推送目标,二者不可同时使用。
解决步骤
获取Firebase服务账号密钥
登录Firebase控制台,进入项目设置 → 服务账号 → 生成新的私钥,下载JSON格式的密钥文件,放到项目的WEB-INF目录下。手动初始化FirebaseApp
在Servlet的init方法中添加初始化逻辑(确保只执行一次),避免每次请求重复检查。修正消息构建逻辑
删除setTopic或setToken其中一个,只保留一种推送目标。
修改后的完整代码示例
@Override public void init() throws ServletException { super.init(); // 仅在Servlet启动时初始化一次FirebaseApp if (FirebaseApp.getApps().isEmpty()) { try { // 获取密钥文件的真实路径 String keyPath = getServletContext().getRealPath("/WEB-INF/firebase-service-account.json"); FileInputStream serviceAccount = new FileInputStream(keyPath); FirebaseOptions options = new FirebaseOptions.Builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) .build(); FirebaseApp.initializeApp(options); } catch (IOException e) { e.printStackTrace(); throw new ServletException("初始化FirebaseApp失败", e); } } } protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); try{ String registrationToken = "你的Android设备注册令牌"; // 构建消息,二选一指定推送目标 Message message = Message.builder() .putData("score", "850") // 目标1:指定单个设备令牌 .setToken(registrationToken) // 目标2:指定主题(需要注释掉上面的setToken) // .setTopic("Topic") .build(); String result = FirebaseMessaging.getInstance().send(message); System.out.println("消息发送成功: " + result); } catch(FirebaseMessagingException e){ System.err.println("发送失败: " + e.getMessage()); e.printStackTrace(); } }
内容的提问来源于stack exchange,提问作者Shekhar J. Lobo
相关产品推荐
相关产品推荐

