소스 검색

系统首页

buzhanyi 2 년 전
부모
커밋
680f2526f0

+ 470 - 0
vehicle-admin/src/main/java/com/ozs/web/controller/websocket/JPushUtil.java

@@ -0,0 +1,470 @@
+package com.ozs.web.controller.websocket;
+
+import cn.jiguang.common.resp.APIConnectionException;
+import cn.jiguang.common.resp.APIRequestException;
+import cn.jpush.api.JPushClient;
+import cn.jpush.api.push.PushResult;
+import cn.jpush.api.push.model.Message;
+import cn.jpush.api.push.model.Options;
+import cn.jpush.api.push.model.Platform;
+import cn.jpush.api.push.model.PushPayload;
+import cn.jpush.api.push.model.audience.Audience;
+import cn.jpush.api.push.model.notification.AndroidNotification;
+import cn.jpush.api.push.model.notification.IosNotification;
+import cn.jpush.api.push.model.notification.Notification;
+import cn.jpush.api.schedule.ScheduleResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @Author : sunhh
+ * @create 2023/3/14 11:20
+ */
+@Slf4j
+@Component
+public class JPushUtil {
+
+    private final static String APPKER = "1712ced750e33d75d18cb577";
+    private final static String MASTERSECRET = "e4b8ba2eda2acd0f75177b88";
+    // 极光demo
+    // private final static String APPKER = "2a59ed096611fb4b82f08a44";
+    // private final static String MASTERSECRET = "a121413e4b89b0a4b3998fe0";
+
+    /**
+     * 推送给设备标识参数的用户
+     */
+    public static int sendToRegistrationId(List<String> alias, String notification_title, String msg_title, String msg_content, String extrasparam) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectAllAliasAlertWithTitle(alias, notification_title, msg_title, msg_content, extrasparam);
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            if (pushResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]PushResult result is " + pushResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 推送给指定设备标识参数的用户(自定义消息通知)
+     *
+     * @param alias              设备标识 用户ID 别名
+     * @param notification_title 通知内容标题
+     * @param msg_title          消息内容标题
+     * @param msg_content        消息内容
+     * @param extrasparam        扩展字段(通常传跳转的链接)
+     * @return 0推送失败,1推送成功
+     */
+    public static int sendToRegistrationId(String alias, String notification_title, String msg_title, String msg_content, String extrasparam) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObject_all_alias_alertWithTitle(alias, notification_title, msg_title, msg_content, extrasparam);
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            if (pushResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]PushResult result is " + pushResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 推送给设备标识参数的用户(定时)
+     */
+    public static int sendToRegistrationId2(List<String> alias, String notification_title, String msg_title, String msg_content, String extrasparam, String time) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectAllAliasAlertWithTitle(alias, notification_title, msg_title, msg_content, extrasparam);
+            ScheduleResult scheduleResult = jPushClient.createSingleSchedule("测试", time, pushPayload);
+            if (scheduleResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]ScheduleResult result is " + scheduleResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 发送给所有安卓用户
+     */
+    public static int sendToAllAndroid(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectAndroidAllAlertWithTitle(notification_title, msg_title, msg_content, extrasparam);
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            if (pushResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]PushResult result is " + pushResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 发送给所有IOS用户
+     */
+    public static int sendToAllIos(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectIosAllAlertWithTitle(notification_title, msg_title, msg_content, extrasparam);
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            if (pushResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]PushResult result is " + pushResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 发送给所有用户
+     */
+    public static int sendToAll(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectAndroidAndIos(notification_title, msg_title, msg_content, extrasparam);
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            if (pushResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]PushResult result is " + pushResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 发送给所有用户(定时推送)
+     */
+    public static int sendToAll2(String notification_title, String msg_title, String msg_content, String extrasparam, String time) {
+        JPushClient jPushClient = new JPushClient(MASTERSECRET, APPKER);
+        int result = 0;
+        try {
+            PushPayload pushPayload = JPushUtil.buildPushObjectAndroidAndIos(notification_title, msg_title, msg_content, extrasparam);
+            ScheduleResult scheduleResult = jPushClient.createSingleSchedule("测试", time, pushPayload);
+            if (scheduleResult.getResponseCode() == 200) {
+                result = 1;
+            }
+            log.info("[极光推送]scheduleResult result is " + scheduleResult);
+        } catch (APIConnectionException e) {
+            log.error("[极光推送]Connection error. Should retry later. ", e);
+        } catch (APIRequestException e) {
+            log.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
+            log.info("[极光推送]HTTP Status: " + e.getStatus());
+            log.info("[极光推送]Error Code: " + e.getErrorCode());
+            log.info("[极光推送]Error Message: " + e.getErrorMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 推送自定义消息 指定别名推送
+     *
+     * @param alias
+     * @param notification_title
+     * @param msg_title
+     * @param msg_content
+     * @param extrasparam
+     * @return
+     */
+    private static PushPayload buildPushObject_all_alias_alertWithTitle(String alias, String notification_title, String msg_title, String msg_content, String extrasparam) {
+        //创建一个IosAlert对象,可指定APNs的alert、title等字段
+        //IosAlert iosAlert =  IosAlert.newBuilder().setTitleAndBody("title", "alert body").build();
+        return PushPayload.newBuilder()
+                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
+                .setPlatform(Platform.all())
+                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
+                .setAudience(Audience.alias(alias))
+                //.setAudience(Audience.all()) //所有人
+                //.setAudience(Audience.registrationId(registrationId)) //注册ID
+                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
+                .setNotification(Notification.newBuilder()
+                        //指定当前推送的android通知
+                        .addPlatformNotification(AndroidNotification.newBuilder()
+                                .setAlert(msg_content)
+                                .setTitle(notification_title)
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                .build())
+                        //指定当前推送的iOS通知
+                        .addPlatformNotification(IosNotification.newBuilder()
+                                //传一个IosAlert对象,指定apns title、title、subtitle等
+                                .setAlert(msg_content)
+                                //直接传alert
+                                //此项是指定此推送的badge自动加1
+                                .incrBadge(1)
+                                //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
+                                // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
+                                .setSound("sound.caf")
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
+                                //取消此注释,消息推送时ios将无法在锁屏情况接收
+                                // .setContentAvailable(true)
+                                .build())
+                        .build())
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msg_content)
+                        .setTitle(msg_title)
+                        //.addExtra("url", extrasparam) //释放该字段会发送两次消息,第二次消息内容是扩展字段
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(true)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天; 秒为单位
+                        .setTimeToLive(1 * 60 * 60 * 24)
+                        .build())
+                .build();
+    }
+
+    public static PushPayload buildPushObjectAndroidAndIos(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        return PushPayload.newBuilder()
+                .setPlatform(Platform.android_ios())
+                .setAudience(Audience.all())
+                .setNotification(Notification.newBuilder()
+                        .setAlert(msg_content)
+                        .addPlatformNotification(AndroidNotification.newBuilder()
+                                .setAlert(msg_content)
+                                .setTitle(notification_title)
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                .build()
+                        )
+                        .addPlatformNotification(IosNotification.newBuilder()
+                                //传一个IosAlert对象,指定apns title、title、subtitle等
+                                .setAlert(msg_content)
+                                //直接传alert
+                                //此项是指定此推送的badge自动加1
+                                .incrBadge(1)
+                                //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
+                                // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
+                                .setSound("sound.caf")
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
+                                // .setContentAvailable(true)
+                                .build()
+                        )
+                        .build()
+                )
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msg_content)
+                        .setTitle(msg_title)
+                        .addExtra("url", extrasparam)
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(true)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
+                        .setTimeToLive(86400)
+                        .build()
+                )
+                .build();
+    }
+
+    private static PushPayload buildPushObjectAllAliasAlertWithTitle(List<String> alias, String notification_title, String msg_title, String msg_content, String extrasparam) {
+        //创建一个IosAlert对象,可指定APNs的alert、title等字段
+        //IosAlert iosAlert =  IosAlert.newBuilder().setTitleAndBody("title", "alert body").build();
+        return PushPayload.newBuilder()
+                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
+                .setPlatform(Platform.all())
+                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
+                .setAudience(Audience.registrationId(alias))
+//                .setAudience(Audience.registrationId(registrationId))
+                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
+                .setNotification(Notification.newBuilder()
+                        //指定当前推送的android通知
+                        .addPlatformNotification(AndroidNotification.newBuilder()
+                                .setAlert(msg_content)
+                                .setTitle(notification_title)
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                .build())
+                        //指定当前推送的iOS通知
+                        .addPlatformNotification(IosNotification.newBuilder()
+                                //传一个IosAlert对象,指定apns title、title、subtitle等
+                                .setAlert(msg_content)
+                                //直接传alert
+                                //此项是指定此推送的badge自动加1
+                                .incrBadge(1)
+                                //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
+                                // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
+                                .setSound("sound.caf")
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
+                                //取消此注释,消息推送时ios将无法在锁屏情况接收
+                                // .setContentAvailable(true)
+                                .build())
+                        .build())
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msg_content)
+                        .setTitle(msg_title)
+                        .addExtra("url", extrasparam)
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(true)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天;
+                        .setTimeToLive(86400)
+                        .build())
+                .build();
+    }
+
+    private static PushPayload buildPushObjectAndroidAllAlertWithTitle(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        return PushPayload.newBuilder()
+                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
+                .setPlatform(Platform.android())
+                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
+                .setAudience(Audience.all())
+                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
+                .setNotification(Notification.newBuilder()
+                        //指定当前推送的android通知
+                        .addPlatformNotification(AndroidNotification.newBuilder()
+                                .setAlert(msg_content)
+                                .setTitle(notification_title)
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                .build())
+                        .build()
+                )
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msg_content)
+                        .setTitle(msg_title)
+                        .addExtra("url", extrasparam)
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(true)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
+                        .setTimeToLive(86400)
+                        .build())
+                .build();
+    }
+
+    private static PushPayload buildPushObjectIosAllAlertWithTitle(String notification_title, String msg_title, String msg_content, String extrasparam) {
+        return PushPayload.newBuilder()
+                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
+                .setPlatform(Platform.ios())
+                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
+                .setAudience(Audience.all())
+                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
+                .setNotification(Notification.newBuilder()
+                        //指定当前推送的android通知
+                        .addPlatformNotification(IosNotification.newBuilder()
+                                //传一个IosAlert对象,指定apns title、title、subtitle等
+                                .setAlert(msg_content)
+                                //直接传alert
+                                //此项是指定此推送的badge自动加1
+                                .incrBadge(1)
+                                //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
+                                // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
+                                .setSound("sound.caf")
+                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                .addExtra("url", extrasparam)
+                                //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
+                                // .setContentAvailable(true)
+                                .build())
+                        .build()
+                )
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msg_content)
+                        .setTitle(msg_title)
+                        .addExtra("url", extrasparam)
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(true)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
+                        .setTimeToLive(86400)
+                        .build())
+                .build();
+    }
+
+//    public static void main(String[] args) {
+//        List<String> alias = new ArrayList<String>();
+//        alias.add("sunhh");
+////        alias.add("wangyy");
+//        //sendToRegistrationId(alias, "中奖通知", "中奖通知", "恭喜你中了100个亿!", "https://www.baidu.com");
+//        //sendToRegistrationId2(alias,"中奖通知", "中奖通知", "恭喜你中了100个亿!", "https://www.baidu.com","2021-07-14 17:54:00");
+////        sendToAllAndroid("中奖通知!!!!", "中奖通知!!!!!", "恭喜你中了100000000个亿!!!!", "https://www.baidu.com");
+//         sendToAllIos("中奖通知", "中奖通知", "恭喜你中了100个亿", "https://www.baidu.com");
+//         // sendToAll("中奖通知", "中奖通知", "恭喜你中了100个亿!", "https://www.baidu.com");
+//        //sendToAll2("中奖通知", "中奖通知", "恭喜你中了100个亿!", "https://www.baidu.com","2021-07-14 17:54:00");
+//    }
+}

+ 21 - 0
vehicle-admin/src/main/java/com/ozs/web/controller/websocket/WebSocketConfig.java

@@ -0,0 +1,21 @@
+package com.ozs.web.controller.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @Author : sunhh
+ * @create 2023/3/7 16:17
+ */
+@Configuration
+public class WebSocketConfig {
+    /**
+     * 注入ServerEndpointExporter,
+     * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
+     */
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+}

+ 140 - 0
vehicle-admin/src/main/java/com/ozs/web/controller/websocket/WebSocketServer.java

@@ -0,0 +1,140 @@
+package com.ozs.web.controller.websocket;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * @Author : sunhh
+ * @create 2023/3/7 16:15
+ */
+@Slf4j
+@Component
+@ServerEndpoint("/websocket/{userId}")  // 接口路径 ws://localhost:8087/webSocket/userId;
+public class WebSocketServer {
+
+    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
+    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
+    //  注:底下WebSocket是当前类名
+    private static CopyOnWriteArraySet<WebSocketServer> webSockets = new CopyOnWriteArraySet<>();
+    // 用来存在线连接用户信息
+    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();
+    //与某个客户端的连接会话,需要通过它来给客户端发送数据
+    private Session session;
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 获取用户是否在线
+     */
+    public boolean userOnline(String userId) {
+        Session session = sessionPool.get(userId);
+        return session != null ? true : false;
+    }
+
+    /**
+     * 链接成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
+        try {
+            this.session = session;
+            this.userId = userId;
+            webSockets.add(this);
+            sessionPool.put(userId, session);
+            log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
+        } catch (Exception e) {
+        }
+    }
+
+    /**
+     * 链接关闭调用的方法
+     */
+    @OnClose
+    public void onClose() {
+        try {
+            webSockets.remove(this);
+            sessionPool.remove(this.userId);
+            log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
+        } catch (Exception e) {
+        }
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message
+     */
+    @OnMessage
+    public void onMessage(String message) {
+        log.info("【websocket消息】收到客户端消息:" + message);
+    }
+
+    /**
+     * 发送错误时的处理
+     *
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+
+        log.error("用户错误,原因:" + error.getMessage());
+        error.printStackTrace();
+    }
+
+
+    // 此为广播消息
+    public void sendAllMessage(String message) {
+        log.info("【websocket消息】广播消息:" + message);
+        for (WebSocketServer webSocket : webSockets) {
+            try {
+                if (webSocket.session.isOpen()) {
+                    webSocket.session.getAsyncRemote().sendText(message);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // 此为单点消息
+    public void sendOneMessage(String userId, String message) {
+        Session session = sessionPool.get(userId);
+        if (session != null && session.isOpen()) {
+            try {
+                log.info("【websocket消息】 单点消息:" + message);
+                session.getAsyncRemote().sendText(message);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // 此为单点消息(多人)
+    public void sendMoreMessage(String[] userIds, String message) {
+        for (String userId : userIds) {
+            Session session = sessionPool.get(userId);
+            if (session != null && session.isOpen()) {
+                try {
+                    log.info("【websocket消息】 单点消息:" + message);
+                    session.getAsyncRemote().sendText(message);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+    }
+}