springboot 接入websocket实现定时推送消息到客户端
创始人
2024-05-24 00:38:08
0

在这里插入图片描述

目录

  • 说明
  • 代码实现

说明

如标题,举例需求场景:
前端与后端websocket连接上后,多用户登录,后端根据不同用户定时发消息给前端用于展示

代码实现

1、

org.springframework.bootspring-boot-starter-websocket

2、

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Component
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}}

3、

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.io.IOException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;// 交给IOC容器
@Component
// 如果去掉/{userId} 那就是不分用户 给连接上的用户统一发送消息
@ServerEndpoint("/websocket/{userId}")
@Slf4j
public class WebSocketService {// 这里用ConcurrentHashMap 因为他是一个线程安全的Mapprivate static ConcurrentHashMap> userwebSocketMap = new ConcurrentHashMap<>();private static ConcurrentHashMap count = new ConcurrentHashMap<>();private String userId;/** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 连接建立成功调用的方法** @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") final String userId) {this.session = session;this.userId = userId;System.out.println("session:" + session);System.out.println("userId:" + userId);if (!exitUser(userId)) {initUserInfo(userId);} else {CopyOnWriteArraySet webSocketServiceSet = getUserSocketSet(userId);webSocketServiceSet.add(this);userCountIncrease(userId);}System.out.println("有" + userId + "新连接加入!当前在线人数为" + getCurrUserCount(userId));}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {CopyOnWriteArraySet webSocketServiceSet = userwebSocketMap.get(userId);//从set中删除webSocketServiceSet.remove(this);//在线数减1userCountDecrement(userId);System.out.println("有一连接关闭!当前在线人数为" + getCurrUserCount(userId));}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息* @param session 可选的参数*/@OnMessagepublic void onMessage(String message, Session session) {CopyOnWriteArraySet webSocketSet = userwebSocketMap.get(userId);System.out.println("来自客户端" + userId + "的消息:" + message);//群发消息for (WebSocketService item : webSocketSet) {try {item.sendMessage(message);} catch (IOException e) {e.printStackTrace();continue;}}}/*** 发生错误时调用** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {System.out.println("发生错误");error.printStackTrace();}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。** @param message* @throws IOException*/public void sendMessage(String message) throws IOException {System.out.println("服务端推送" + userId + "的消息:" + message);this.session.getAsyncRemote().sendText(message);}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。   我是在有代办消息时 调用此接口 向指定用户发送消息** @param message* @throws IOException*/public void sendMessage(String userId, String message) throws IOException {System.out.println("服务端推送" + userId + "的消息:" + message);CopyOnWriteArraySet webSocketSet = userwebSocketMap.get(userId);//群发消息for (WebSocketService item : webSocketSet) {try {item.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();continue;}}}public void sendOpenAllUserMessage(List userIds, String message) {for (String userId : userIds) {CopyOnWriteArraySet webSocketSet = userwebSocketMap.get(userId);//群发消息for (WebSocketService item : webSocketSet) {try {item.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();continue;}}}}public boolean exitUser(String userId) {return userwebSocketMap.containsKey(userId);}public CopyOnWriteArraySet getUserSocketSet(String userId) {return userwebSocketMap.get(userId);}public void userCountIncrease(String userId) {if (count.containsKey(userId)) {count.put(userId, count.get(userId) + 1);}}public void userCountDecrement(String userId) {if (count.containsKey(userId)) {count.put(userId, count.get(userId) - 1);}}public void removeUserConunt(String userId) {count.remove(userId);}public Integer getCurrUserCount(String userId) {return count.get(userId);}private void initUserInfo(String userId) {CopyOnWriteArraySet webSocketServiceSet = new CopyOnWriteArraySet();webSocketServiceSet.add(this);userwebSocketMap.put(userId, webSocketServiceSet);count.put(userId, 1);}public List getAllUser() {List allUser = new LinkedList<>();Enumeration keys = userwebSocketMap.keys();while (keys.hasMoreElements()) {String key = keys.nextElement();allUser.add(key);}return allUser;}}

4、

import com.lq.demo1.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;import java.util.List;@EnableScheduling
@Configuration
@Slf4j
public class TaskTimer {@Autowiredprivate WebSocketService webSocketService;@Scheduled(cron = "0/10 * * * * ?")public void cleanToken() {//10s推送一次List allUser = webSocketService.getAllUser();//自己可以定义不同用户发送的信息,这里不做演示了webSocketService.sendOpenAllUserMessage(allUser, "告警!");}}

@EnableScheduling
在这里插入图片描述

然后把项目启动,打开在线调试websocket连接

路径格式为:ws://localhost:8081/websocket/1
在这里插入图片描述

在这里插入图片描述

成功展示,也可以搞多个窗口,发送内容一致

就先说到这\color{#008B8B}{ 就先说到这}就先说到这
在下Apollo\color{#008B8B}{在下Apollo}在下Apollo
一个爱分享Java、生活的小人物,\color{#008B8B}{一个爱分享Java、生活的小人物,}一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞!\color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!}咱们来日方长,有缘江湖再见,告辞!

在这里插入图片描述

相关内容

热门资讯

唐诗之李商隐:无题·其二 唐诗三百首之李商隐:无题·其二唐诗三百首全集《无题·其二》作者:李商隐飒飒东风细雨来,芙蓉塘外有轻雷...
鲁迅《淡淡的血痕中》原文及读... 鲁迅《淡淡的血痕中》原文及读后感  【鲁迅《淡淡的血痕中》原文】  —纪念几个死者和生者和未生者— ...
适合儿童的唐诗 适合儿童的唐诗  唐诗的'辉煌成就,引起后人学习的兴趣和研究的热望。下面就是小编给大家整理的幼儿唐诗...
嫦娥 李商隐 嫦娥 李商隐嫦娥 李商隐,此其诗诗题为“嫦娥”,实际上抒写的是处境孤寂的主人公对于环境的感受和心灵独...
咏秋古诗词 中秋将至,秋风猎猎,秋高气爽。作为我国的传统节日,古代诗词中有很多千古传颂的咏秋之作,以诗抒情怀,以...
谷雨的古诗句 谷雨的古诗句  谷雨的雨,现身在古代文人墨客笔下,是相当愁人的。小编今天为大家带来关于谷雨的.古诗句...
表达奉献精神的诗句 表达奉献精神的诗句  在日常学习、工作和生活中,大家总少不了接触一些耳熟能详的诗句吧,诗句能使人们自...
经典爱情现代诗   经典爱情现代诗  1、《炉中煤》  啊,我年青的女郎!  我不辜负你的殷勤,  你也不要辜负了我...
描写兰花的诗句分享 描写兰花的诗句分享  丛兰生幽谷,莓莓遍林薄。不纫亦何伤,已胜当门托。辇至逾关山,滋培珍几阁。  冬...
朱自清的代表作品有哪些 朱自清的代表作品有哪些  朱自清(1898.11.22—1948.8.12)原名自华,号秋实,后改名...
春思诗,春思诗谢朓,春思诗的... 春思诗,春思诗谢朓,春思诗的意思,春思诗赏析 -诗词大全  春思诗,春思诗谢朓,春思诗的意思,春思诗...
客醉倚河桥,清光愁玉箫 “客醉倚河桥,清光愁玉箫。”出处 出自 宋代 高观国 的《菩萨蛮·何须急管吹云暝》“客醉倚河桥,清光...
古代的诗词歌赋 古代的诗词歌赋五篇  导语:诗词歌赋是专门集我国历代名家精品如唐诗宋词元曲为一体的诗词歌赋作品的软件...
唯美古诗句子 唯美古诗句子  山无陵,江水为竭,冬雷震震,夏雨雪,天地合,乃敢与君绝!下文就是有关描写唯美古诗句子...
花的古诗 关于花的古诗大全  古诗是古代中国诗歌的泛称,指古代中国人创作的诗歌作品。广义的古诗包括诗、词、散曲...
《武陵春·风住尘香花已尽》李... 《武陵春·风住尘香花已尽》李清照宋词翻译及赏析  赏析,是一个汉语词汇,意思是欣赏并分析(诗文等),...
中秋节的诗歌 中秋节的诗歌  1、《月之故乡》  彭邦桢  水里一个月亮  天上一个月亮  天上的月亮在水里  水...
中国经典古诗词 有关中国经典古诗词  在学习、工作或生活中,许多人对一些广为流传的古诗都不陌生吧,古诗是中文独有的一...
描写夏天的古诗 关于描写夏天的古诗  夏天是我们喜爱的季节之一,那么,关于描写夏天的古诗有哪些呢?下面是unjs小编...
苏轼的诗句都有哪些 苏轼的诗句都有哪些  苏轼的诗句都有哪些呢,大家感兴趣了解一下吗?以下是小编为大家整理的关于苏轼的诗...