0


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

WebSocket–入门

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

WebSocket简介

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

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

依赖导入

<!-- 该依赖包含 SpringBoot starer 无需重复导入 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.0</version></dependency><!-- 除此之外我们还需要lombok 和 fastjson --><!-- 这里就不导入了 -->

代码实现

WebSocketConfig

importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.socket.server.standard.ServerEndpointExporter;@ConfigurationpublicclassWebSocketConfig{@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}

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

importlombok.Data;@DatapublicclassNoticeWebsocketResp<T>{privateString noticeType;privateT noticeInfo;}

WebSocketServer

importcom.alibaba.fastjson.JSONObject;importcom.mydemo.websocketdemo.domain.NoticeWebsocketResp;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importorg.springframework.util.StringUtils;importjavax.websocket.*;importjavax.websocket.server.PathParam;importjavax.websocket.server.ServerEndpoint;importjava.io.IOException;importjava.util.*;importjava.util.concurrent.ConcurrentHashMap;@ServerEndpoint("/notice/{userId}")@Component@Slf4jpublicclassNoticeWebsocket{//记录连接的客户端publicstaticMap<String,Session> clients =newConcurrentHashMap<>();/**
     * userId关联sid(解决同一用户id,在多个web端连接的问题)
     */publicstaticMap<String,Set<String>> conns =newConcurrentHashMap<>();privateString sid =null;privateString userId;/**
     * 连接成功后调用的方法
     * @param session
     * @param userId
     */@OnOpenpublicvoidonOpen(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 =newHashSet<>();
            conns.put(userId,clientSet);}
        clientSet.add(this.sid);
        log.info(this.sid +"连接开启!");}/**
     * 连接关闭调用的方法
     */@OnClosepublicvoidonClose(){
        log.info(this.sid +"连接断开!");
        clients.remove(this.sid);}/**
     * 判断是否连接的方法
     * @return
     */publicstaticbooleanisServerClose(){if(NoticeWebsocket.clients.values().size()==0){
            log.info("已断开");returntrue;}else{
            log.info("已连接");returnfalse;}}/**
     * 发送给所有用户
     * @param noticeType
     */publicstaticvoidsendMessage(String noticeType){NoticeWebsocketResp noticeWebsocketResp =newNoticeWebsocketResp();
        noticeWebsocketResp.setNoticeType(noticeType);sendMessage(noticeWebsocketResp);}/**
     * 发送给所有用户
     * @param noticeWebsocketResp
     */publicstaticvoidsendMessage(NoticeWebsocketResp noticeWebsocketResp){String message =JSONObject.toJSONString(noticeWebsocketResp);for(Session session1 :NoticeWebsocket.clients.values()){try{
                session1.getBasicRemote().sendText(message);}catch(IOException e){
                e.printStackTrace();}}}/**
     * 根据用户id发送给某一个用户
     * **/publicstaticvoidsendMessageByUserId(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();}}}}}}/**
     * 收到客户端消息后调用的方法
     * @param message
     * @param session
     */@OnMessagepublicvoidonMessage(String message,Session session){
        log.info("收到来自窗口"+this.userId+"的信息:"+message);}/**
     * 发生错误时的回调函数
     * @param error
     */@OnErrorpublicvoidonError(Throwable error){
        error.printStackTrace();}}

这样我们就配置好了websocket

测试准备

访问接口–当请求该接口时,主动推送消息
importcom.mydemo.websocketdemo.domain.NoticeWebsocketResp;importcom.mydemo.websocketdemo.websocketserver.NoticeWebsocket;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/order")publicclassOrderController{@GetMapping("/test")publicStringtest(){NoticeWebsocket.sendMessage("你好,WebSocket");return"ok";}@GetMapping("/test1")publicStringtest1(){NoticeWebsocketResp noticeWebsocketResp =newNoticeWebsocketResp();
        noticeWebsocketResp.setNoticeInfo("米奇妙妙屋");NoticeWebsocket.sendMessageByUserId("1", noticeWebsocketResp);return"ok";}}
springboot启动类
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassWebSocketApplication{publicstaticvoidmain(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 =newWebSocket('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

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

标签: 前端 java

本文转载自: https://blog.csdn.net/qq_45770147/article/details/130011485
版权归原作者 Yuyan_I 所有, 如有侵权,请联系我们删除。

“websockets-后端主动向前端推送消息”的评论:

还没有评论