Spring+React PWA Web Push实现及通知无提示问题求助
Spring后端向React PWA推送Web通知方案及Firebase推送问题修复
一、替代webpush-java的后端实现方案
1. Firebase Admin SDK(推荐,与前端Firebase集成统一)
官方维护,稳定性强,适合已使用Firebase前端的场景:
- Maven依赖配置:
<dependency> <groupId>com.google.firebase</groupId> <artifactId>firebase-admin</artifactId> <version>9.2.0</version> <!-- 替换为最新稳定版 --> </dependency> - 初始化配置:
@Configuration public class FirebaseConfig { @Bean public FirebaseApp firebaseApp() throws IOException { try (FileInputStream serviceAccount = new FileInputStream("classpath:serviceAccountKey.json")) { FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) .build(); return FirebaseApp.initializeApp(options); } } } - 推送发送逻辑:
@Service public class PushService { private final FirebaseMessaging firebaseMessaging; public PushService(FirebaseMessaging firebaseMessaging) { this.firebaseMessaging = firebaseMessaging; } public void sendPush(String userToken, String title, String body) throws FirebaseMessagingException { Message message = Message.builder() .setToken(userToken) .setData(Map.of( "title", title, "body", body, "tag", "event-notification" )) .build(); firebaseMessaging.send(message); } }
2. 维护活跃的Web Push Java库:nl.martijndwars/web-push
无需依赖Firebase,直接基于Web Push协议实现:
- Maven依赖配置:
<dependency> <groupId>nl.martijndwars</groupId> <artifactId>web-push</artifactId> <version>5.1.1</version> <!-- 最新版 --> </dependency> - 核心推送代码:
前端需先获取用户的public class WebPushNotificationService { private final PushService pushService; public WebPushNotificationService() throws GeneralSecurityException, IOException { // 生成VAPID密钥对(前端需用公钥获取用户订阅) VapidDetails vapidDetails = new VapidDetails( "mailto:your-support@example.com", "YOUR_VAPID_PUBLIC_KEY", "YOUR_VAPID_PRIVATE_KEY" ); this.pushService = new PushService(vapidDetails); } public void sendNotification(PushSubscription subscription, String payload) throws IOException, GeneralSecurityException { pushService.send(subscription, payload); } }PushSubscription对象,传给后端存储,后续用该对象推送。
二、Firebase推送无声音、振动的修复方案
你的通知能显示但无提醒,主要是以下几点问题及解决方法:
1. 强制使用data-only payload
如果后端推送包含notification字段,系统会直接接管通知展示,跳过onBackgroundMessage的自定义配置。后端要只传data字段:
// 后端发送的Message示例 Message message = Message.builder() .setToken(userToken) .setData(Map.of( "title", "事件提醒", "body", "您关注的事件已发生", "tag", "event-tag" )) .build();
2. 完善notificationOptions配置
添加声音参数,明确禁用静音:
messaging.onBackgroundMessage((payload) => { const notificationTitle = payload.data.title; const notificationOptions = { body: payload.data.body, tag: payload.data?.tag, renotify: true, requireInteraction: true, vibrate: [500, 200, 500, 200, 100, 200, 100], icon: './images/icons/icon-128x128.png', badge: './images/icons/icon-128x128.png', sound: 'default', // 使用系统默认通知音 silent: false, // 明确设置非静音 actions: [] // 可选,添加交互按钮 }; self.registration.showNotification(notificationTitle, notificationOptions); });
自定义声音需确保音频文件在service worker作用域内,比如/sounds/alert.mp3,设置sound: '/sounds/alert.mp3'。
3. 确认权限与系统设置
- 前端需请求通知权限:
async function initNotifications() { const permission = await Notification.requestPermission(); if (permission !== 'granted') { throw new Error('通知权限未授予'); } } - 检查设备系统设置:确保设备全局通知声音、振动开启,且PWA应用的通知设置中单独允许声音和振动(部分安卓设备需单独配置)。
4. 验证service worker作用域
service worker文件需放在根目录(或通过scope参数指定正确范围),确保能捕获background message,且资源路径(icon、sound)相对于service worker的路径正确。
内容的提问来源于stack exchange,提问作者LCh
相关产品推荐
相关产品推荐

