如何从Spring Boot向Flutter应用发送推送通知?
实现Spring Boot定时推送+Flutter接收的完整方案
一、Spring Boot端:用Cron表达式配置定时任务
首先在Spring Boot启动类开启定时任务支持,然后编写定时任务类指定执行时间:
@SpringBootApplication @EnableScheduling // 开启定时任务功能 public class PushServerApplication { public static void main(String[] args) { SpringApplication.run(PushServerApplication.class, args); } } @Component public class PushScheduler { @Autowired private PushService pushService; // 每天早8点执行推送,Cron格式:秒 分 时 日 月 周 年(可选) @Scheduled(cron = "0 0 8 * * ?") public void sendDailyPush() { pushService.sendNotificationToAllUsers(); } }
常用Cron表达式示例:
- 每小时执行一次:
0 0 * * * ? - 每分钟执行一次:
0 * * * * ? - 每周一上午9点:
0 0 9 ? * MON
如果需要指定时区,在application.yml中配置:
spring: scheduler: timezone: Asia/Shanghai
二、Spring Boot端:实现推送核心逻辑
以Firebase Cloud Messaging(FCM)为例,先添加依赖:
<dependency> <groupId>com.google.firebase</groupId> <artifactId>firebase-admin</artifactId> <version>9.2.0</version> </dependency>
然后编写推送服务类,从数据库获取用户设备token(Flutter端注册后上传),批量发送通知:
@Service public class PushService { private final FirebaseMessaging firebaseMessaging; private final UserRepository userRepository; @Autowired public PushService(FirebaseMessaging firebaseMessaging, UserRepository userRepository) { this.firebaseMessaging = firebaseMessaging; this.userRepository = userRepository; } public void sendNotificationToAllUsers() { // 从数据库查询所有用户的FCM设备token List<String> userTokens = userRepository.findAllDeviceTokens(); MulticastMessage message = MulticastMessage.builder() .setNotification(Notification.builder() .setTitle("每日提醒") .setBody("今天也要加油哦!") .build()) .addAllTokens(userTokens) .build(); try { BatchResponse response = firebaseMessaging.sendMulticast(message); System.out.println("成功推送:" + response.getSuccessCount() + "条"); System.out.println("失败推送:" + response.getFailureCount() + "条"); } catch (FirebaseMessagingException e) { e.printStackTrace(); } } }
三、Flutter端:接收推送通知
先在pubspec.yaml添加依赖:
dependencies: firebase_messaging: ^14.6.5 flutter_local_notifications: ^16.1.0
然后编写推送服务类,完成权限申请、token获取上传、通知监听:
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:http/http.dart' as http; class PushNotificationService { final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initialize() async { // 请求用户通知权限 NotificationSettings settings = await _firebaseMessaging.requestPermission( alert: true, badge: true, sound: true, ); if (settings.authorizationStatus == AuthorizationStatus.authorized) { // 获取设备FCM token并上传到服务器 String? token = await _firebaseMessaging.getToken(); if (token != null) { await _uploadTokenToServer(token); } // 监听token刷新,及时更新服务器存储 FirebaseMessaging.onTokenRefresh.listen((newToken) { _uploadTokenToServer(newToken); }); // 前台接收通知时弹出本地通知 FirebaseMessaging.onMessage.listen((RemoteMessage message) { RemoteNotification? notification = message.notification; AndroidNotification? android = message.notification?.android; if (notification != null && android != null) { _flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, NotificationDetails( android: AndroidNotificationDetails( 'daily_remind_channel', '日常提醒', channelDescription: '接收服务器定时推送的提醒', icon: '@mipmap/ic_launcher', ), ), ); } }); // 后台点击通知时跳转指定页面 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { print('通知被点击:${message.notification?.title}'); // 这里可以添加页面跳转逻辑,比如Navigator.push(context, ...) }); } } Future<void> _uploadTokenToServer(String token) async { // 调用Spring Boot接口上传token await http.post( Uri.parse('http://你的服务器地址/api/user/token'), body: {'token': token}, ); } }
最后在main函数初始化推送服务:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await PushNotificationService().initialize(); runApp(const MyApp()); }
四、关键注意事项
- Token生命周期:FCM token可能会过期或更新,必须通过
onTokenRefresh监听并同步到服务器,避免推送失败。 - 定时任务可靠性:Spring Boot原生
@Scheduled适合简单定时场景,如果需要持久化未执行任务、分布式调度,建议替换为Quartz框架。 - 推送权限:Flutter端必须获得用户授权才能接收通知,否则即使服务器发送成功,设备也收不到。
- 时区一致性:确保Spring Boot服务器时区、Cron表达式时区和业务需求一致,避免推送时间偏差。
内容的提问来源于stack exchange,提问作者Luis Rotoly
相关产品推荐
相关产品推荐

