技术标签: 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、效果:
文章浏览阅读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
文章浏览阅读579次。redhat Linux怎么安装该文件火狐(Firefox-latest.tar.bz2)2012-11-29 21:05提问者: 魔教教神 |浏览次数:187次问题补充:解压后的目录平常用的软件,外面下的还要挂载,还要共享,这个我菜鸟不能一步登上去。。。我来帮他解答推荐答案2012-11-29 21:40_linux firefox 源码安装
文章浏览阅读268次。FlowStep3D: Model Unrolling for Self-Supervised Scene Flow Estimation cvpr 2021 开源代码地址和光流的RAFT有很大的相同之处。一:Idea 传统的基于学习的端到端三维流学习方法的泛化能力较差 提出了一个循环架构,它学习了展开迭代对齐过程的单个步骤,用于精炼场景流预测。 我们建议在更深、更低分辨率的空间中有效地使用它主要Idea来源RAFT: Recurrent All-Pairs Field Tra_flowstep3d
文章浏览阅读2k次,点赞3次,收藏2次。家里有nas需要防止断电不正常关机,因此购买了施耐德后背式BP650CH,之所以选这款是因为带了串口,串口终究还是很方便的东西。测试1:关闭UPS的市电输入,蜂鸣器10秒叫一次,QS命令检索状态发现UPS的状态字节最高位变成了1,这个时候就可以通知用户进行关机了。由于这个施耐德的UPS串口并非终端交互式的,因此我们不适合用SecureCRT,采用其他输入和输出分离的串口助手。默认波特兰2400,8bit数据,1bit停止位,无检验。退出minicom方法,ctrl+A后,然后按Z,然后按X,然后yes。_ups与nas 直接通信
文章浏览阅读3.8k次,点赞4次,收藏6次。最近没事想做个消消乐,然后听说 iVX 免费了,所以又跑去看看 iVX 了,就用一个无代码来看看消消乐怎么玩吧。首先咱们打开 iVX 的在线编辑器:https://editor.ivx.cn/随后选择相对定位,咱们不需要游戏类型也可以制作一个消消乐游戏:接着创建两个页面,一个是开始页面,还有一个是游戏页面:随后在开始页面中编辑页面如下所示:接着咱们在游戏页面中创建以下不同类似的变量:接着咱们在源一维数组中添加图片的地址:接着在游戏界面中创建如下组件,使用循环组建遍历对应的游戏数据:_消消乐网页版
文章浏览阅读1.9k次。树的后序遍历(递归和非递归java实现)_编写tree类中的postorder方法,实现树的后根遍历,其中的访问操作调用visit(data)
文章浏览阅读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如何查询银行的余额
文章浏览阅读3.6k次,点赞48次,收藏71次。本文介绍如何利用 Streamlit 搭建个人博客网站,将 Markdown 文章和图像展示在交互式界面中。无需繁琐前端开发,我们通过 Python 编写代码,创造出美观功能丰富的博客。文章解释了读取 Markdown、处理图片链接、构建多页面交互等技术,同时涵盖发布网站至 Streamlit Cloud。通过 Streamlit,我们以创新方式与读者互动,将复杂内容以直观方式展示。这篇文章为初次尝试使用 Streamlit 的人提供了实用指南,激发大家在交互式数据应用方面的创造力。_用streamlit做的blog
文章浏览阅读545次。所谓地推,就是地面推广的意思。区别于线上推广,地推是需要人力现场去做的,常见的就是让人扫二维码关注公众号或者是下载APP。如今互联网红利期消失,流量被垄断,原本低成本的线上推广变得越来越烧钱,单纯的线上推广已经很难再获取到用户流量了,直接面对用户的地推变成众多App推广的出路。那么策划一个App地推活动需要做些什么呢?1、首先明确地推的目的:地推活动的目的可以是拉新、促销、引流、品牌宣传等等,地推活动目的的不同,则地推活动的方案也会有所不同,因此在撰写地推方案的时候需要确定好地推活动的目的。2、确定目_地推的博客-csdn博客
文章浏览阅读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 校验不通过
文章浏览阅读372次。如何远程连接阿里云ECS服务器Windows实例?远程连接登录 Windows 实例的方式多种多样,阿里云控制台管理终端、windows系统远程连接工具及手机客户端都能实现远程连接。我们来详细介绍如何远程连接并登录Windows实例。远程连接操作步骤首先,您需要运行这台实例,确保状态为运行中,获取实例IP地址。接下来,我们使用远程桌面连接实例,在开始菜单栏输入mstsc打开客户端。在“计算机”处..._局域网的机器如何连接到阿里云ecs
文章浏览阅读1.3k次。 如何使用java向mysql存取二进制图片2007-05-18 18:40前几天突然看到学校音乐站上的图片原来是存储在数据库上的,是二进制而不是使用路径保存的,在网上招了找发现大多介绍的都是hph方式,在这里做个总结,首先要存储二进制文件在数据库中要搞清楚下面几个内容:1 mysql存储大容量的二进制文件的格式是blob,其实除了图片还可以存别的2 _mysql 数据库存储二进制图片