vue中使用WebSocket与java SpringBoot进行交互实现聊天室
一、简单介绍下HTML5 WebSocketWebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。在 WebSocket API ...
·
一、简单介绍下HTML5 WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
ok,WebSocket 能实现的通信相关的功能有很多,例如:聊天室,扫码等,这里就是实现的聊天室,下面来看是如何进行交互的!!!(这里默认已经有vue项目基础 && 后端语言为java)
二、前端 VUE: 与WebSocket交互
1.使用样例(无掺杂属于自己的业务)
<template>
<div>
WebSocket
</div>
</template>
<script>
export default {
created() {
this.initWebSocket(); //进入页面开始初始化websocket建立连接
},
destroyed() {
this.websocketclose(); //离开页面断开连接
},
methods: {
initWebSocket() {
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
this.websock = new WebSocket("wss://localhost"); //这里是websocket服务地址,这里的地址可以前端根据后台地址参数规则拼成,也可以向后端请求
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onmessage = this.websocketonmessage;
this.websock.onclose = this.websocketclose;
},
websocketonopen() {
console.log("WebSocket连接成功");
},
websocketonerror(e) {
console.log("WebSocket连接发生错误");
},
websocketonmessage(e) {
console.log(e.data); // console.log(e);
},
websocketclose(e) {
console.log("connection closed (" + e.code + ")");
},
}
}
</script>
2.项目样例(WebSocket实现 聊天室并加入聊天弹幕 功能,弹幕插件使用具体可以 点击查看)
created() {
this.t = window.setInterval(this.getChatUserList, 5000);
},
beforeDestroy() {
clearInterval(this.t);
},
destroyed() {
this.websocketClose();
}
methods: {
// 初始化 websocket 连接
initWebSocket() {
if (typeof WebSocket != "undefined") {
this.supported = "支持 websocket";
} else {
this.supported = "不支持 websocket";
}
//ws地址
var wsAbaseUrl = abaseUrl.substring(abaseUrl.lastIndexOf("/") + 1);
const wsuri = "wss://" + wsAbaseUrl + "/websocket/" + this.$route.query.liveId + "/" + this.type + "/" + this.userId;
this.chatRoomWebsocket = new WebSocket(wsuri);
this.chatRoomWebsocket.onerror = this.websocketOnError;
this.chatRoomWebsocket.onmessage = this.websocketOnMessage;
this.chatRoomWebsocket.onclose = this.websocketOnClose;
},
//连接发生错误的回调方法
websocketOnError() {
console.log("WebSocket 连接发生错误");
},
//接收到消息的回调方法
websocketOnMessage(event) {
console.log(event);
let data = JSON.parse(event.data);
this.msgHeadImageURL = data.chatImage ? data.chatImage : userPhoto;
if (data.chatUser != this.userId) {
this.msgs.push(data);
this.barrageList.push({
id: ++this.currentId,
avatar: this.msgHeadImageURL,
msg: data.chatContent,
barrageStyle: "normal",
time: 5,
type: 0,
position: "bottom"
});
}
},
//连接关闭的回调方法
websocketOnClose(e) {
console.log("WebSocket 连接关闭", e);
},
//关闭 WebSocket 连接
websocketClose() {
this.chatRoomWebsocket.close();
},
//发送弹幕+发送消息
addToList() {
if (this.sendmsg.split(" ").join("").length != 0) {
//获取当前时间
var time = new Date();
this.sendTime =
time.getHours() +
":" +
(time.getMinutes() < 10
? "0" + time.getMinutes()
: time.getMinutes());
let messageData = {
chatContent: this.sendmsg,
chatUser: this.userId,
chatAvatar: this.userInfo.nickName,
chatImage: this.headImageURL,
chatTime: this.sendTime
};
if (this.chatRoomWebsocket.readyState != "1") {
// 如果按下按钮时不是连接状态,重连并等到连接成功再发送消息
this.initWebSocket();
this.chatRoomWebsocket.onopen = () => {
this.chatRoomWebsocket.send(JSON.stringify(messageData));
//发送消息
this.msgs.push({
chatContent: this.sendmsg
});
//弹幕
this.msgHeadImageURL = this.headImageURL
? this.headImageURL
: userPhoto;
this.barrageList.push({
id: ++this.currentId,
avatar: this.msgHeadImageURL,
msg: this.sendmsg,
barrageStyle: "normal",
time: 5,
type: 0,
position: "bottom"
});
this.sendmsg = "";
};
} else {
this.chatRoomWebsocket.send(JSON.stringify(messageData));
//发送消息
this.msgs.push({
chatContent: this.sendmsg
});
//弹幕
this.msgHeadImageURL = this.headImageURL
? this.headImageURL
: userPhoto;
this.barrageList.push({
id: ++this.currentId,
avatar: this.msgHeadImageURL,
msg: this.sendmsg,
barrageStyle: "normal",
time: 5,
type: 0,
position: "bottom"
});
this.sendmsg = "";
}
}
},
//定时器获取总人数以及列表
getChatUserList() {
let data = {
sid: this.$route.query.liveId,
type: 1
};
onlineList(data).then(res => {
if (res.data.state == 200) {
this.onlineNumber = res.data.data.count;
this.onlineUserList = res.data.data.userList;
}
});
},
},
三、后端 java SpringBoot 2.++:相关配置(后端相关配置粘自后端,勿喷~)
1.pom文件中添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
2.WebSocket配置类
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
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.根据业务逻辑WebSocket操作类
package com.library.style.assembly;
import com.alibaba.druid.util.StringUtils;
import com.library.style.model.User;
import com.library.style.repository.UserRepository;
import com.library.style.utils.JsonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
@RestController
@ServerEndpoint(value = "/websocket/{sid}/{type}/{userId}") //房间号、类型(1,直播聊天)、用户Id、
@Component
public class WebSocket {
private static WebSocket webSocket;
private static Logger logger = LoggerFactory.getLogger(WebSocket.class);
//当前连接数
private static int onlineCount = 0;
//存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
//与某个客户端的连接会话
private Session session;
//客户端唯一标识sid(直播ID)
private String sid = "";
//用户类型
private Integer type=0;
//用户ID
private Integer userId = 0;
//用户昵称
private String nickName="";
//用户头像地址
private String headImageUrl="";
@Autowired
private UserRepository userRepository;
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
@PostConstruct
public void init() {
webSocket = this;
webSocket.userRepository = this.userRepository;
}
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid, @PathParam("type") Integer type,@PathParam("userId") Integer userId) {
moreWindow(sid,userId,type);
//在线数加1
addOnlineCount();
this.session = session;
//加入set中
webSocketSet.add(this);
this.sid = sid;
this.userId = userId;
this.type=type;
User user=WebSocket.webSocket.userRepository.findById(userId).get();
this.nickName=user.getNickName();
this.headImageUrl=user.getHeadImageURL();
logger.info("用户ID:"+userId+"用户昵称:"+nickName+"新连接:sid=" + sid + " 当前在线人数" + getOnlineCount());
try {
sendMessage("连接成功");
} catch (IOException e) {
logger.error("websocket IO异常");
}
}
@OnMessage
public void onMessage(String message, Session session) {
//群发消息
for (WebSocket item : webSocketSet) {
try {
if(item.sid.equals(this.sid)){
item.sendMessage(message);
System.out.println("--------------------"+message+"总人数"+onlineCount);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 同一用户打开多个窗口问题
*
* @param sid
*/
public void moreWindow(String sid,Integer userId,Integer type) {
if (StringUtils.isEmpty(sid)) {
return;
}
if(webSocketSet.isEmpty()){
return;
}
for (WebSocket item : webSocketSet) {
if (item.sid.equals(sid)&&item.userId.equals(userId)&&item.type==type) {
//已经有相同的了
webSocketSet.remove(item);
subOnlineCount();
}
}
}
/**
* 发送消息给指定用户
*
* @param message
* @param sid
*/
public static void sendMessage(String message, @PathParam("sid") String sid) {
logger.info("发送消息:sid=" + sid + " message:" + message);
for (WebSocket item : webSocketSet) {
try {
if (sid == null) {
item.sendMessage(message);
System.out.println("+++++++++++++++"+message);
} else if (item.sid.equals(sid)) {
logger.info("开始发送消息:sid=" + sid);
item.sendMessage(message);
}
} catch (IOException e) {
logger.error("发送消息失败 sid:"+sid,e);
continue;
}
}
}
@OnClose
public void onClose() {
logger.info("连接关闭:sid=" + sid + " 当前在线人数" + getOnlineCount());
webSocketSet.remove(this);
subOnlineCount();
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
/**
* 当前在线人数
* @return
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 添加在线人数
*/
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
/**
* 减少在线人数
*/
public static synchronized void subOnlineCount() {
if (WebSocket.onlineCount <= 0) {
WebSocket.onlineCount = 0;
return;
}
WebSocket.onlineCount--;
}
/**
* 人数列表
*/
@PostMapping(value = "/numberList")
public JsonResult numberList(@RequestParam(value = "sid") String sid,@RequestParam(value = "type") Integer type){
Map map=new HashMap<>();
List<User> userList=new ArrayList<>();
Integer count=0;
for (WebSocket item : webSocketSet) {
if(item.sid!=null&&item.sid.equals(sid)&&item.type==type){
User user=new User();
user.setNickName(item.nickName);
user.setUserId(item.userId);
user.setHeadImageURL(item.headImageUrl);
userList.add(user);
count++;
}
}
map.put("userList",userList);
map.put("count",count);
return new JsonResult(map);
}
}
更多推荐
已为社区贡献12条内容
所有评论(0)