springboot快速集成websocket实现群聊

springboot快速集成websocket实现群聊

  • 添加pom依赖
1
2
3
4
5
<!-- springboot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  • java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package cn.pconline.pcloud.admin.config;

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

/**
* @Description WebSocket配置
* @Author jie.zhao
* @Date 2020/3/23 18:32
*/
@Configuration
public class WebSocketConfig {
//实例化一个Bean对象
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package cn.pconline.pcloud.admin.controller.api;

import cn.pconline.framework.enums.MessageTypeEnum;
import cn.pconline.pcloud.base.dto.MessageDto;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
* @Description 群聊websocket
* @Author jie.zhao
* @Date 2020/3/23 18:34
*/
@Component
@ServerEndpoint("/groupChat/{groupNo}/{name}")
public class GroupChatWebsocket {

private Logger logger = LoggerFactory.getLogger(getClass());

/**
* 保存 组id->组成员 的映射关系
* 之所以使用ConcurrentHashMap因为这个是线程安全的
*/
private static ConcurrentHashMap<String, List<Session>> groupMemberInfoMap = new ConcurrentHashMap<>();

/**
* 收到消息调用的方法,群成员发送消息
*
* @param groupNo
* @param name
* @param message
*/
@OnMessage
public void onMessage(@PathParam("groupNo") String groupNo,
@PathParam("name") String name, String message) {
//得到当前群的所有会话,也就是所有用户
List<Session> sessionList = groupMemberInfoMap.get(groupNo);
MessageDto dto = new MessageDto();
dto.setType(MessageTypeEnum.CHAT.getType());
dto.setOnlineNum(sessionList.size());
// 遍历Session集合给每个会话发送文本消息
sessionList.forEach(item -> {
try {
dto.setName(name);
dto.setContent(message);
item.getBasicRemote().sendText(JSON.toJSONString(dto));
} catch (IOException e) {
e.printStackTrace();
}
});
}

/**
* 建立连接调用的方法,群成员加入
*
* @param session 会话
* @param groupNo 群id
*/
@OnOpen
public void onOpen(Session session, @PathParam("groupNo") String groupNo) {
//得到当前群的所有会话,也就是所有用户
List<Session> sessionList = groupMemberInfoMap.get(groupNo);
if (sessionList == null) {
sessionList = new ArrayList<>();
groupMemberInfoMap.put(groupNo, sessionList);
}
sessionList.add(session);
logger.info("连接建立");
logger.info("直播房间号: {}, 直播在线人数: {}", groupNo, sessionList.size());
systemOnlineNumMsg(sessionList, sessionList.size());
}

/**
* 关闭连接调用的方法,群成员退出
*
* @param session
* @param groupNo
*/
@OnClose
public void onClose(Session session, @PathParam("groupNo") String groupNo) {
List<Session> sessionList = groupMemberInfoMap.get(groupNo);
sessionList.remove(session);
logger.info("连接关闭");
logger.info("直播房间号: {}, 直播在线人数: {}", groupNo, sessionList.size());
systemOnlineNumMsg(sessionList, sessionList.size());
}

/**
* 传输消息错误调用的方法
*
* @param error
*/
@OnError
public void OnError(Throwable error) {
logger.info("连接出错:{}", error.getMessage());
}

/**
* 在线人数系统通知
* @param sessionList
* @param onlineNum
*/
public void systemOnlineNumMsg(List<Session> sessionList , int onlineNum) {
// 遍历Session集合给每个会话发送文本消息
MessageDto dto = new MessageDto();
dto.setType(MessageTypeEnum.SYSTEM.getType());
sessionList.forEach(item -> {
try {
dto.setOnlineNum(onlineNum);
item.getBasicRemote().sendText(JSON.toJSONString(dto));
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package cn.pconline.pcloud.admin.controller.api;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* @Description 测试
* @Author jie.zhao
* @Date 2020/3/23 18:41
*/
@Controller
@RequestMapping("/api")
public class TestChatController {

@RequestMapping("/test")
public String index(){
return "api/test";
}
}
  • 测试html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>直播互动</title>
<!--适应移动端-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--css样式-->
<style>
body{ margin:0 auto; width:400px; border:1px solid #F00}
.box{margin:20px;}
</style>
<!--引用jquery库-->
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

</head>

<body>
<div class="box">
<p>直播房间号</p>
<input type="text" id="groupNo" value="1585023517289" placeholder="请输入房间号"/>
<p>昵称</p>
<input type="text" id="name" value="" placeholder="请输入昵称"/>
<p>聊天内容</p>
<textarea rows="3" cols="20" id="content" placeholder="请输入聊天内容"></textarea> <br/>
<input type="submit" value="发送" onclick="start()"/>
<p>-----------------------------------------</p>
<div id="messages" style=""></div>
</div>

<script type="text/javascript">

var webSocket = null;

//收到消息
function onMessage(event) {
$('#messages').append('<p>'+ event.data+'</p>');
}

//建立连接
function onOpen(event) {
console.log('连接已经建立');
}

//发生错误
function onError(event) {
console.log('发生错误');
webSocket = null;
}

//连接关闭
function onClose(event) {
console.log('连接关闭');
webSocket = null;
}

//连接
function connect() {
//获取群号
var groupNo = $('#groupNo').val();
//获取昵称
var name = $('#name').val();
//验证非法数据
if (url == '' || name == '') {
alert('群号和用户名不能为空');
return;
}
//验证是否已经建立连接
if (webSocket != null) {
alert('已经建立过连接,如需重新建立连接,请自行更改逻辑,或者重新刷新页面');
return;
}
//创建Websocket连接url
var url = 'ws://127.0.0.1:8080/cisco/groupChat/' + groupNo + '/' + name;
//实例化WebSocket
try {
webSocket = new WebSocket(url);
}catch(err){
}
//出现错误
webSocket.onerror = function (event) {
onError(event)
};
//调用创建连接
webSocket.onopen = function (event) {
onOpen(event)
};
//调用收到消息
webSocket.onmessage = function (event) {
onMessage(event)
};
//调用关闭连接
webSocket.onclose = function (event) {
onClose(event)
};
}

//开始发送
function start() {
//获取发送的内容
var text = $('#content').val();
if (text == '') {
alert('发送内容不允许为空');
return;
}
if (webSocket == null) {
console.log('连接已关闭,正在重新连接');
connect();
}
//调用WebSocket发送的方法
webSocket.send(text);
//初始化文本域的内容为空
$('#content').val('')
}

//连接检测,重试连接
function wsCheck() {
setTimeout(function () {
if (webSocket == null) {
connect();
console.log('连接健康监测:'+(webSocket!=null?'ok':'error'));
}
wsCheck();
}, 1000 * 10);
}


window.onload = function(){

var name = $.cookie('cisco-cookie-name');

if(name==null||name==''){
name = '游客'+ Date.parse(new Date());
$.cookie('cisco-cookie-name', name, { expires: 7 });
}

$('#name').val(name)
connect();
wsCheck();
}

</script>
</body>
</html>
-------------已经触及底线 感谢您的阅读-------------

本文标题:springboot快速集成websocket实现群聊

文章作者:趙小傑~~

发布时间:2020年03月24日 - 18:46:59

最后更新:2020年03月24日 - 18:53:39

原始链接:https://cnsyear.com/posts/277b2c5f.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%