详解springboot springsecuroty中的注销和权限控制问题
411
2022-08-06
SpringBoot整合websocket实现即时通信聊天(websocket实现即时通讯)
目录一、技术介绍1.1 客户端WebSocket1.1.1 函数1.1.2 事件1.2 服务端WebSocket二、实战 2.1、服务端2.1.1引入maven依赖2.1.2 编写配置类2.1.3 编写WebSocketService服务类2.1.4 建立连接2.1.5 关闭连接2.1.6 发送消息2.1.7 监听错误2.2 客户端2.2.1 主页面2.2.1 聊天页面三、开源地址四、参考文献
一、技术介绍
线上演示地址:http://chat.breez.work
实时通信(Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。[4]
场景再现:
微信聊天QQ聊天网站在线客服
1.1 客户端WebSocket
WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。使用 WebSocket() 构造函数来构造一个 WebSocket。[1]
构造函数如下所示:
const webSocket = WebSocket(url[, protocols])
例子如下:
const webSocket = new WebSocket("ws://42.193.120.86:3688/ws/小明/翠花")
1.1.1 函数
1、 webSocket.send()该函数用于向服务端发送一条消息,例子如下:
webSocket.send("Hello server!");
2、 webSocket.close()该函数用于关闭客户端与服务端的连接,例子如下:
webSocket.close();
1.1.2 事件
1、webSocket.onopen该事件用于监听客户端与服务端的连接状态,如果客户端与服务端连接成功则该事件触发,例子如下:
webSocket.onopen = function(event) {
console.log("连接已经建立,可以进行通信");
};
2、webSocket.onclose如果服务端与客户端连接断开,那么此事件出发,例子如下:
webSocket.onclose = function(event) {
console.log("连接已经关闭");
};
3、webSocket: message event该事件用于监听服务端向客户端发送的消息,例子如下:
webSocket.addEventListener('message', function (event) {
console.log('来自服务端的消息:', event.data);
});
4、webSocket:error event如果客户端与服务端发生错误时,那么此事件将会触发,例子如下:
webSocket.addEventListener('error', function (event) {
console.log('连接出现错误', event);
});
1.2 服务端WebSocket
@ServerEndpoint用于声明一个socket服务,例子如下:
@ServerEndpoint(value = "/ws/{userId}/{targetId}")
几个重要的方法注解:
@OnOpen 打开连接@OnClose 监听关闭@OnMessage 发送消息@OnError 监听错误
二、实战
2.1、服务端
2.1.1引入maven依赖
2.1.2 编写配置类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
2.1.3 编写WebSocketService服务类
下面的userId代表发送者的ID号,target代表发送目标ID号。
@Component
@ServerEndpoint(value = "/ws/{userId}/{target}")
public class WebSocketService {
//用于保存连接的用户信息
private static ConcurrentHashMap
//原子递增递减,用于统计在线用户数
private static AtomicInteger count = new AtomicInteger();
//消息队列,用于保存待发送的信息
private Queue
//onOpen()
//onClose()
//onMessage()
//onError()
}
2.1.4 建立连接
建立连接之前,判断用户是否已经连接,如果没有连接,那么将用户session信息保存到集合,然后计数器递增。
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
if (!SESSION.containsKey(userId)) {
SESSION.put(userId, session);
count.incrementAndGet();
}
}
2.1.5 关闭连接
关闭连接的时候,将用户session删除和计数器递减。
@OnClose
public void onClose(@PathParam("userId") String userId) {
SESSION.remove(userId);
count.decrementAndGet();
}
2.1.6 发送消息
发送采用的方法是:session.getBasicRemote().sendText("你好");
@OnMessage
public void onMessage(String message, @PathParam("userId") String userId, @PathParam("target") String target) throws IOException {
queue.add(message);
Session s = SESSION.get(target);
if (s == null) {
Session b = SESSION.get(userId);
b.getBasicRemote().sendText("对方不在线");
} else {
for (int i = 0; i < queue.size(); i++) {
String msg = queue.poll();
Message m = new Message();
m.setUserId(userId);
s.getBasicRemote().sendText(msg);
}
}
}
2.1.7 监听错误
出现错误,删除用户session信息和计数器递减
@OnError
public void onError(Throwable error, @PathParam("userId") String userId) {
SESSION.remove(userId);
count.decrementAndGet();
error.printStackTrace();
}
2.2 客户端
本案例中客户端采用Nuxt编写,相关代码如下
2.2.1 主页面
运行截图如图所示:
export default {
name: 'IndexPage',
data() {
return {
formInline: {
userId: '',
targetId: ''
},
rules: {
userId: [{
required: true,
message: '请输入你的喵喵号',
trigger: 'blur'
}],
targetId: [{
required: true,
message: '请输入对方喵喵号',
trigger: 'blur'
}]
}
}
},
methods: {
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$router.push({
name: 'chat',
params: this.formInline
})
} else {
console.log('error submit!!');
return false;
}
});
}
},
created() {
}
}
body {
background: url('../static/img/cat.jpg');
}
2.2.1 聊天页面
运行截图如下:小明
翠花
&lhttp://t;div>
我的喵喵号:
对方喵喵号:
{{m.msg}}
{{m.msg}}
export default {
name: 'ChatPage',
data() {
return {
url: 'localhost:3688/ws/1001/1002',
msg: '',
socket: {},
msg_status: true,
msgList: [],
initList: [],
count: 0,
user: {
userId: '',
targetId: ''
}
}
},
created() {
const userId = this.$route.params.userId
const targetId = this.$route.params.targetId
if (userId !== undefined && targetId !== undefined) {
this.user.userId = userId
this.user.targetId = targetId
this.connect()
} else {
this.$router.push("/")
}
},
methods: {
//创建socket客户端
connect() {
var that = this
this.socket = new WebSocket("ws://42.193.120.86:3688/ws/" + this.user.userId + "/" + this.user.targetId);
this.socket.onclose = function(event) {
that.$message('连接关闭');
};
this.socket.addEventListener('error', function(event) {
that.$message.error('出现错误');
});
// 监听消息
this.socket.addEventListener('message', function(event) {
that.msgList.push({
type: 2,
msg: event.data
})
console.log(event.data);
console.log({
type: 2,
msg: event.data
});
});
this.socket.onopen = function(event) {
that.msg_status = false
that.msgList.push({
type: 3,
msg: '连接成功'
})
};
},
clearMsg() {
this.$confirm('确认清空?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.msgList = []
})
},
//发送消息
sendMessage() {
this.socket.send(this.msg)
this.msgList.push({
type: 1,
msg: this.msg
})
this.msg = ''
}
}
}
三、开源地址
Gitee:https://gitee.com/BreezAm/websocket
演示地址:http://chat.breez.work
四、参考文献
[1]MDN:WebSocket
[2]Nuxt:https://nuxtjs.org
[3]vue:https://cn.vuejs.org
[4]百度百科:及时通信
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~