文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

websockets-后端主动向前端推送消息

2023-09-11 21:13

关注

公司领导提出了一个新的需求,那就是部门主管在有审批消息的情况下,需要看到提示消息。其实这种需求最简单的方法使接入短信、邮件、公众号平台。直接推送消息。但是,由于使自研项目,公司领导不想花钱,只能另辟蹊径。

WebSocket简介

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。

WebSocket-实现后端推送消息给前端

依赖导入

<dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-websocketartifactId>    <version>2.7.0version>dependency>

代码实现

WebSocketConfig

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

WebSocketMessage–封装的消息结果类(非必须)

import lombok.Data;@Datapublic class NoticeWebsocketResp<T> {    private String noticeType;    private T noticeInfo;}

WebSocketServer

import com.alibaba.fastjson.JSONObject;import com.mydemo.websocketdemo.domain.NoticeWebsocketResp;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.*;import java.util.concurrent.ConcurrentHashMap;@ServerEndpoint("/notice/{userId}")@Component@Slf4jpublic class NoticeWebsocket {    //记录连接的客户端    public static Map<String, Session> clients = new ConcurrentHashMap<>();        public static Map<String, Set<String>> conns = new ConcurrentHashMap<>();    private String sid = null;    private String userId;        @OnOpen    public void onOpen(Session session, @PathParam("userId") String userId) {        this.sid = UUID.randomUUID().toString();        this.userId = userId;        clients.put(this.sid, session);        Set<String> clientSet = conns.get(userId);        if (clientSet==null){            clientSet = new HashSet<>();            conns.put(userId,clientSet);        }        clientSet.add(this.sid);        log.info(this.sid + "连接开启!");    }        @OnClose    public void onClose() {        log.info(this.sid + "连接断开!");        clients.remove(this.sid);    }        public static boolean isServerClose() {        if (NoticeWebsocket.clients.values().size() == 0) {            log.info("已断开");            return true;        }else {            log.info("已连接");            return false;        }    }        public static void sendMessage(String noticeType){        NoticeWebsocketResp noticeWebsocketResp = new NoticeWebsocketResp();        noticeWebsocketResp.setNoticeType(noticeType);        sendMessage(noticeWebsocketResp);    }        public static void sendMessage(NoticeWebsocketResp noticeWebsocketResp){        String message = JSONObject.toJSONString(noticeWebsocketResp);        for (Session session1 : NoticeWebsocket.clients.values()) {            try {                session1.getBasicRemote().sendText(message);            } catch (IOException e) {                e.printStackTrace();            }        }    }        public static void sendMessageByUserId(String userId, NoticeWebsocketResp noticeWebsocketResp) {        if (!StringUtils.isEmpty(userId)) {            String message = JSONObject.toJSONString(noticeWebsocketResp);            Set<String> clientSet = conns.get(userId);            if (clientSet != null) {                Iterator<String> iterator = clientSet.iterator();                while (iterator.hasNext()) {                    String sid = iterator.next();                    Session session = clients.get(sid);                    if (session != null) {                        try {session.getBasicRemote().sendText(message);                        } catch (IOException e) {e.printStackTrace();                        }                    }                }            }        }    }        @OnMessage    public void onMessage(String message, Session session) {        log.info("收到来自窗口"+this.userId+"的信息:"+message);    }        @OnError    public void onError(Throwable error) {        error.printStackTrace();    }}

这样我们就配置好了websocket

测试准备

访问接口–当请求该接口时,主动推送消息
import com.mydemo.websocketdemo.domain.NoticeWebsocketResp;import com.mydemo.websocketdemo.websocketserver.NoticeWebsocket;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/order")public class OrderController {    @GetMapping("/test")    public String test() {        NoticeWebsocket.sendMessage("你好,WebSocket");        return "ok";    }    @GetMapping("/test1")    public String test1() {        NoticeWebsocketResp noticeWebsocketResp = new NoticeWebsocketResp();        noticeWebsocketResp.setNoticeInfo("米奇妙妙屋");        NoticeWebsocket.sendMessageByUserId("1", noticeWebsocketResp);        return "ok";    }}
springboot启动类
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class WebSocketApplication {    public static void main(String[] args) {        SpringApplication.run(WebSocketApplication.class,args);    }}
前端测试页面
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>SseEmitter</title></head><body><div id="message"></div></body><script>var limitConnect = 0;init();function init() {// 8080未默认端口,可自行替换    var ws = new WebSocket('ws://localhost:8080/notice/2');// 获取连接状态console.log('ws连接状态:' + ws.readyState);//监听是否连接成功ws.onopen = function () {    console.log('ws连接状态:' + ws.readyState);    limitConnect = 0;    //连接成功则发送一个数据    ws.send('我们建立连接啦');}// 接听服务器发回的信息并处理展示ws.onmessage = function (data) {    console.log('接收到来自服务器的消息:');    console.log(data);    //完成通信后关闭WebSocket连接    // ws.close();}// 监听连接关闭事件ws.onclose = function () {    // 监听整个过程中websocket的状态    console.log('ws连接状态:' + ws.readyState);reconnect();}// 监听并处理error事件ws.onerror = function (error) {    console.log(error);}}function reconnect() {    limitConnect ++;    console.log("重连第" + limitConnect + "次");    setTimeout(function(){        init();    },2000);   }</script></html>

之后用浏览器打开html页面,显示如下:

请添加图片描述

连接成功

调用接口

localhost:8080/order/test

请添加图片描述
证明后端推送消息给前端成功

来源地址:https://blog.csdn.net/qq_45770147/article/details/130011485

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯