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}{咱们来日方长,有缘江湖再见,告辞!}咱们来日方长,有缘江湖再见,告辞!

在这里插入图片描述

相关内容

热门资讯

小学贫困生申请书 小学贫困生申请书  贫困生申请书范文(一)  尊敬的领导:  我叫李xxx,家住东镇镇中羊泉西村,在...
孩子改名申请书范文   孩子的名字会影响孩子的一生,如果一开始起名不够优雅可以再去修改,下面就是小编为您收集整理的孩子改...
贫困生补助申请理由 贫困生补助申请理由200字(精选10篇)  一些贫困生因家庭经济困难,申请贫困补助,这个时候需要去撰...
如何写申请书 如何写申请书  一、申请书的含义  申请书是个人或集体向组织、机关、企事业单位或社会团体表述愿望、提...
解除财产保全申请书 解除财产保全申请书解除财产保全申请书 第一篇:解除财产保全书范文申请人:王XX,女,白族,1983年...
事故索赔申请书 事故索赔申请书范文(精选5篇)  随着社会在进步,申请书与我们不再陌生,申请书不同于其他书信,是一种...
入团申请书 入团申请书模板400字(通用15篇)  在当今社会生活中,很多场合都离不了申请书,利用申请书我们可以...
困难救助申请书 困难救助申请书(精选7篇)  在眼下市场经济活跃的社会,我们会使用上申请书,不同的使用场景有不同的申...
助学金申请表申请理由模板 助学金申请表申请理由模板  一、国家助学金的基本申请条件  ①热爱社会主义祖国,拥护中国共产党的领导...
售后申请报告范文18篇 售后申请报告范文 第一篇亲爱的领导:从我踏出校门的那一刻,满怀壮志的灵魂早已被阴暗的墙壁磨损殆尽。由...
签证专员辞职申请书 签证专员辞职申请书  随着时代在进步,我们会经常使用申请书,请注意不同种类的申请书有着不同的格式。写...
工伤职工申请补偿书范文通用1... 工伤职工申请补偿书范文 第一篇(一)治(医)疗费。治疗工伤所需费用必须符合工伤保险诊疗项目目录、工伤...
村干部入党申请书 最新村干部入党申请书(通用4篇)  在当今社会高速发展的今天申请书起到的作用越来越大,申请书可以使我...
案件答疑申请书范文(推荐5篇... 案件答疑申请书范文 第一篇【申请人理由】上诉人在《民事上诉状》已上诉:一审法官、一审判决书混淆了原告...
申请仲裁书 申请仲裁书模板  申请人:名称:________ 地址:________________  法定代表...
助学金申请理由简短 助学金申请理由简短200字  新的学期开始了,又到申请助学金的时候,那么助学金申请理由怎么写?本文是...
向法院申请强制执行申请书 向法院申请强制执行申请书(精选12篇)  现今社会公众的追求意识不断提升,申请书起到的作用越来越大,...
技术转让专利申请权合同 技术转让(专利申请权)合同合同编号:_________项目名称:_________受让方(甲方):_...
济南公租房申请条件   济南市明确了公租房的申请条件和流程,其中申请条件又分为家庭申请和单身申请、济南市户籍申请和非济南...
大学生贫困助学金申请书 大学生贫困助学金申请书(精选10篇)  在这个高速发展的时代,申请书在生活中的使用越来越广泛,写申请...