赞
踩
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
ok,WebSocket 能实现的通信相关的功能有很多,例如:聊天室,扫码等,这里就是实现的聊天室,下面来看是如何进行交互的!!!(这里默认已经有vue项目基础 && 后端语言为java)
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; } }); }, },
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); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。