jeecgboot websocket 消息_jeecg-boot的websocket-程序员宅基地

技术标签: spring boot  java  websocket  jeecg  

1、添加依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、配置websocket配置类:

package org.jeecg.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    /**
     * 	注入ServerEndpointExporter,
     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
    
}

3、操作工具类:在框架中自带,可进行自定义修改

package org.jeecg.modules.message.websocket;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
    
    private Session session;
    
    private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
    private static Map<String,Session> sessionPool = new HashMap<String,Session>();
    
    @OnOpen
    public void onOpen(Session session, @PathParam(value="userId")String userId) {
        try {
			this.session = session;
			webSockets.add(this);
			sessionPool.put(userId, session);
			log.info("【websocket消息】有新的连接,总数为:"+webSockets.size());
		} catch (Exception e) {
		}
    }
    
    @OnClose
    public void onClose() {
        try {
			webSockets.remove(this);
			log.info("【websocket消息】连接断开,总数为:"+webSockets.size());
		} catch (Exception e) {
		}
    }
    
    @OnMessage
    public void onMessage(String message) {
    	log.info("【websocket消息】收到客户端消息:"+message);
    }
    
    // 此为广播消息
    public void sendAllMessage(String message) {
    	log.info("【websocket消息】广播消息:"+message);
        for(WebSocket 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();
                }
            }
    	}
        
    }
    
}

4、测试:controller 类中测试,可以使用定时或者其他等等方式进行消息的发送


import com.alibaba.fastjson.JSONObject;

@RestController
@RequestMapping("/sys/socketTest")
public class TestSocketController {

    @Autowired
    private WebSocket webSocket;

    @PostMapping("/sendAll")
    public Result<String> sendAll(@RequestBody JSONObject jsonObject) {
    	Result<String> result = new Result<String>();
    	String message = jsonObject.getString("message");
    	JSONObject obj = new JSONObject();
    	obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
		obj.put(WebsocketConst.MSG_ID, "M0001");
		obj.put(WebsocketConst.MSG_TXT, message);
    	webSocket.sendMessage(obj.toJSONString());
        result.setResult("群发!");
        return result;
    }

    @PostMapping("/sendUser")
    public Result<String> sendUser(@RequestBody JSONObject jsonObject) {
    	Result<String> result = new Result<String>();
    	String userId = jsonObject.getString("userId");
    	String message = jsonObject.getString("message");
    	JSONObject obj = new JSONObject();
    	obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
    	obj.put(WebsocketConst.MSG_USER_ID, userId);
		obj.put(WebsocketConst.MSG_ID, "M0001");
		obj.put(WebsocketConst.MSG_TXT, message);
        webSocket.sendMessage(userId, obj.toJSONString());
        result.setResult("单发");
        return result;
    }

}

5、vue端:在App.vue中配置,websocket

<script>
  import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
  import enquireScreen from '@/utils/device'
  import store from '@/store/'
  export default {
    data() {
      return {
        locale: zhCN,
      }
    },
    created() {
      let that = this
      enquireScreen(deviceType => {
        // tablet
        if (deviceType === 0) {
          that.$store.commit('TOGGLE_DEVICE', 'mobile')
          that.$store.dispatch('setSidebar', false)
        }
        // mobile
        else if (deviceType === 1) {
          that.$store.commit('TOGGLE_DEVICE', 'mobile')
          that.$store.dispatch('setSidebar', false)
        } else {
          that.$store.commit('TOGGLE_DEVICE', 'desktop')
          that.$store.dispatch('setSidebar', true)
        }

      })
    },
    mounted() {
      //初始化websocket
      this.initWebSocket()
    },
    destroyed: function () { // 离开页面生命周期函数
      this.websocketclose();
    },
    methods: {
      initWebSocket: function () {
        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
        var userId = store.getters.userInfo.id;
        var url = window._CONFIG['domianURL'].replace("https://", "ws://").replace("http://", "ws://") +
          "/websocket/" + userId;
        this.websock = new WebSocket(url);
        this.websock.onopen = this.websocketonopen;
        this.websock.onerror = this.websocketonerror;
        this.websock.onmessage = this.websocketonmessage;
        this.websock.onclose = this.websocketclose;
      },
      websocketonopen: function () {
        console.log("WebSocket连接成功");
      },
      websocketonerror: function (e) {
        console.log("WebSocket连接发生错误");
      },
      websocketonmessage: function (e) {
        var data = eval("(" + e.data + ")");
        //处理订阅信息
        if (data.cmd == "topic") {
          //TODO 系统通知
          console.log("-----", data)
          this.$notification.open({
            message: 'Notification Title',
            description: data.msgTxt,
            style: {
              width: '600px',
              marginLeft: `${335 - 600}px`,
            },
          });

        } else if (data.cmd == "user") {
          //TODO 用户消息
          console.log("-----", data)
          this.$notification.open({
            message: 'Notification Title',
            description:  data.msgTxt,
            style: {
              width: '600px',
              marginLeft: `${335 - 600}px`,
            },
          });

        }
      },
      websocketclose: function (e) {
        console.log("connection closed (" + e.code + ")");
      }
    }
  }
</script>

6、效果:

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31319235/article/details/120215366

智能推荐

1003. Emergency (25)-PAT甲级真题(Dijkstra算法)_柳婼emergency-程序员宅基地

文章浏览阅读1w次,点赞59次,收藏37次。1003. Emergency (25)As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in..._柳婼emergency

linux安装firefox_linux firefox 源码安装-程序员宅基地

文章浏览阅读579次。redhat Linux怎么安装该文件火狐(Firefox-latest.tar.bz2)2012-11-29 21:05提问者: 魔教教神 |浏览次数:187次问题补充:解压后的目录平常用的软件,外面下的还要挂载,还要共享,这个我菜鸟不能一步登上去。。。我来帮他解答推荐答案2012-11-29 21:40_linux firefox 源码安装

阅读FlowStep3D: Model Unrolling for Self-Supervised Scene Flow Estimation-程序员宅基地

文章浏览阅读268次。FlowStep3D: Model Unrolling for Self-Supervised Scene Flow Estimation​ cvpr 2021 开源代码地址和光流的RAFT有很大的相同之处。一:Idea​ 传统的基于学习的端到端三维流学习方法的泛化能力较差​ 提出了一个循环架构,它学习了展开迭代对齐过程的单个步骤,用于精炼场景流预测。​ 我们建议在更深、更低分辨率的空间中有效地使用它主要Idea来源RAFT: Recurrent All-Pairs Field Tra_flowstep3d

UPS BP650CH实现nas自动关机_ups与nas 直接通信-程序员宅基地

文章浏览阅读2k次,点赞3次,收藏2次。家里有nas需要防止断电不正常关机,因此购买了施耐德后背式BP650CH,之所以选这款是因为带了串口,串口终究还是很方便的东西。测试1:关闭UPS的市电输入,蜂鸣器10秒叫一次,QS命令检索状态发现UPS的状态字节最高位变成了1,这个时候就可以通知用户进行关机了。由于这个施耐德的UPS串口并非终端交互式的,因此我们不适合用SecureCRT,采用其他输入和输出分离的串口助手。默认波特兰2400,8bit数据,1bit停止位,无检验。退出minicom方法,ctrl+A后,然后按Z,然后按X,然后yes。_ups与nas 直接通信

网页版消消乐快速实现,无代码吗iVX 真那么简单?_消消乐网页版-程序员宅基地

文章浏览阅读3.8k次,点赞4次,收藏6次。最近没事想做个消消乐,然后听说 iVX 免费了,所以又跑去看看 iVX 了,就用一个无代码来看看消消乐怎么玩吧。首先咱们打开 iVX 的在线编辑器:https://editor.ivx.cn/随后选择相对定位,咱们不需要游戏类型也可以制作一个消消乐游戏:接着创建两个页面,一个是开始页面,还有一个是游戏页面:随后在开始页面中编辑页面如下所示:接着咱们在游戏页面中创建以下不同类似的变量:接着咱们在源一维数组中添加图片的地址:接着在游戏界面中创建如下组件,使用循环组建遍历对应的游戏数据:_消消乐网页版

树的后序遍历(递归和非递归java实现)_编写tree类中的postorder方法,实现树的后根遍历,其中的访问操作调用visit(data)-程序员宅基地

文章浏览阅读1.9k次。树的后序遍历(递归和非递归java实现)_编写tree类中的postorder方法,实现树的后根遍历,其中的访问操作调用visit(data)

随便推点

SAP EPIC 银企直连 余额查询(建设银行)_sap如何查询银行的余额-程序员宅基地

文章浏览阅读2.2k次。导语:余额查询接口相对比较独立,也比较简单,EPIC_PROC中付款查询是不做存储的,查一次展示一次,每次都要重新查询,本次接口建行的XML跟标准的一致,所以没有做任何改动,直接就可以用,注意客户号等参数赋值正确即可。????【EPIC_PROC银企直连 建设银行】标准类:CL_EPIC_EXAMPLE_CN_CCB_GAB一、创建类复制SAP标准类:CL_EPIC_EXAMPLE_CN_CCB_GAB方法:CREATE_REQUEST METHOD if_epic_bank_comm_im_sap如何查询银行的余额

Streamlit项目: 轻松搭建部署个人博客网站_用streamlit做的blog-程序员宅基地

文章浏览阅读3.6k次,点赞48次,收藏71次。本文介绍如何利用 Streamlit 搭建个人博客网站,将 Markdown 文章和图像展示在交互式界面中。无需繁琐前端开发,我们通过 Python 编写代码,创造出美观功能丰富的博客。文章解释了读取 Markdown、处理图片链接、构建多页面交互等技术,同时涵盖发布网站至 Streamlit Cloud。通过 Streamlit,我们以创新方式与读者互动,将复杂内容以直观方式展示。这篇文章为初次尝试使用 Streamlit 的人提供了实用指南,激发大家在交互式数据应用方面的创造力。_用streamlit做的blog

App地推活动需要做哪些准备 - Xinstall_地推的博客-csdn博客-程序员宅基地

文章浏览阅读545次。所谓地推,就是地面推广的意思。区别于线上推广,地推是需要人力现场去做的,常见的就是让人扫二维码关注公众号或者是下载APP。如今互联网红利期消失,流量被垄断,原本低成本的线上推广变得越来越烧钱,单纯的线上推广已经很难再获取到用户流量了,直接面对用户的地推变成众多App推广的出路。那么策划一个App地推活动需要做些什么呢?1、首先明确地推的目的:地推活动的目的可以是拉新、促销、引流、品牌宣传等等,地推活动目的的不同,则地推活动的方案也会有所不同,因此在撰写地推方案的时候需要确定好地推活动的目的。2、确定目_地推的博客-csdn博客

1分钟解决universal link微信校验不通过_由于应用univer link 校验不通过-程序员宅基地

文章浏览阅读4.2w次。在开发iOS小程序或者微信分享时候,经常提示:由于应用universal link校验不通过,无法按网上的方法,检查各种配置,都未能解决,选择排出以下几个情况1、bundle Id中的teamId写错2、与微信开放平台不一致3、apple-app-site-association链接不能带端口号4、appid和与项目中不匹配5、微信后台设置的universal link 与传到微信sdk不同这些都对过了,都是正确无误,最后实现没有招,用了Xinstall的universal link配置,试了_由于应用univer link 校验不通过

ecs服务器内网连接_如何远程连接阿里云ECS服务器Windows实例?-程序员宅基地

文章浏览阅读372次。如何远程连接阿里云ECS服务器Windows实例?远程连接登录 Windows 实例的方式多种多样,阿里云控制台管理终端、windows系统远程连接工具及手机客户端都能实现远程连接。我们来详细介绍如何远程连接并登录Windows实例。远程连接操作步骤首先,您需要运行这台实例,确保状态为运行中,获取实例IP地址。​接下来,我们使用远程桌面连接实例,在开始菜单栏输入mstsc打开客户端。在“计算机”处..._局域网的机器如何连接到阿里云ecs

如何使用java向mysql存取二进制图片_mysql 数据库存储二进制图片-程序员宅基地

文章浏览阅读1.3k次。 如何使用java向mysql存取二进制图片2007-05-18 18:40前几天突然看到学校音乐站上的图片原来是存储在数据库上的,是二进制而不是使用路径保存的,在网上招了找发现大多介绍的都是hph方式,在这里做个总结,首先要存储二进制文件在数据库中要搞清楚下面几个内容:1 mysql存储大容量的二进制文件的格式是blob,其实除了图片还可以存别的2 _mysql 数据库存储二进制图片

推荐文章

热门文章

相关标签