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

如何从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:02:30