websocket实现简单的消息发送
websocket:
效果图
前端代码
html部分
<div> <!-- <div style="float: left;height: 100vh;width: 1%"></div>--> <div style="float: left;width: 20%;height: 96vh;border-radius: 0.5rem;"> <div class="el-dropdown-link" style="margin-left: 1.6vh;margin-top: 0.7vw;margin-bottom: 0.7vw">返回</div> <div class="info" style="height: 9vh;width: 100%;text-align: center;border-radius: 10px;"> <div style="width: 95%;height: 8vh;border-radius: 0.5rem;margin-left: 3vw;"> <div style="float: left"> <img style="border-radius: 50%;height: 7vh;width: 3.5vw;margin-left: 1rem;margin-right: 0.7rem;margin-top: 1vh;" src="https://cloud-secondhand-trading.oss-cn-shanghai.aliyuncs.com/u%3D3030190913%2C291621981%26fm%3D253%26fmt%3Dauto%26app%3D138%26f%3DJPEG.webp"> </div> <div style="float: left;margin-top: 2vh;font-size: 2.5vh"> {{ userName }} </div> </div> </div> <hr/> <div style="height: 4vh;width: 100%;text-align: center"> <div style="margin-top: 2vh;font-weight: bold;font-size: 2.5vh">消息列表</div> </div> <hr/> <div v-for="(name,index) in userList" :key="name.id"> <div :id="'id'+name.id" class="messagediv" style="width: 95%;height: 7.7vh;border-radius: 0.5rem;" tabindex="2" @click="getStyMessage(name)"> <div style="float: left"> <img style="border-radius: 50%;height: 6.3vh;width: 3vw;margin-left: 1rem;margin-right: 0.7rem;margin-top: 5px;" src="https://cloud-secondhand-trading.oss-cn-shanghai.aliyuncs.com/u%3D3030190913%2C291621981%26fm%3D253%26fmt%3Dauto%26app%3D138%26f%3DJPEG.webp"> </div> <div style="float: left;margin-top: 2vh;font-size: 2.5vh"> {{ name.sender }} </div> </div> <div style="width: 19.5vw"> <hr v-if="index!=list.length-1" style="font-size: 0.001rem;margin-left: 9vh;color: gray;width: 70%;top: -10px"/> </div> </div> </div> <div style="float: left;height: 96vh;width: 0.5%"></div> <div style="float: left;width: 78%;background-color: rgb(250,250,249);height: 96vh;"> <div style="width: 100%;height: 3rem;float: left; text-align: center;background-color: #f0f0f0;border-radius: 0.5rem;"> <div style="margin-top: 0.8rem;font-size: 2.5vh">{{name}}</div> </div> <div style="float: left;clear: left;width: 100%;margin-top: 0.8rem;height: 80vh;overflow: auto"> <div v-for="message in list" :key="message.id"> <div style="text-align: center;width: 100%;font-size: 1.6vh;">{{ message.date }}</div> <div v-if="message.sender!=userName" style="width: 100%;height: 3rem"> <div style="float: left"> <img style="border-radius: 50%;height: 6.3vh;width: 3vw;margin-left: 4rem;margin-right: 0.7rem" src="https://cloud-secondhand-trading.oss-cn-shanghai.aliyuncs.com/u%3D3030190913%2C291621981%26fm%3D253%26fmt%3Dauto%26app%3D138%26f%3DJPEG.webp"> </div> <div> <!-- <div style="margin-left: 0.7rem;font-size: 0.5rem">nih</div>--> <div style="float: left;background-color: white;height: 4.6vh;;border-radius: 10px;margin-top: 0.9vh"> <div style="margin-left: 0.8vw;margin-right: 0.8vw;margin-top:0.68vh;font-size: 2.5vh">{{message.message}}</div> </div> </div> </div> <div v-if="message.sender==userName" style="width: 100%;height: 3rem"> <div style="float: right"> <img style="border-radius: 50%;height: 6.3vh;width: 3vw;margin-right: 4rem;margin-left: 0.7rem" src="https://cloud-secondhand-trading.oss-cn-shanghai.aliyuncs.com/u%3D3030190913%2C291621981%26fm%3D253%26fmt%3Dauto%26app%3D138%26f%3DJPEG.webp"> </div> <div> <!-- <div style="margin-left: 0.7rem;font-size: 0.5rem">nih</div>--> <div style="float: right;background-color: cornflowerblue;height: 4.6vh;border-radius: 10px;margin-top: 0.4rem;"> <div style="margin: 0.27rem;margin-left: 0.7rem;margin-right: 0.7rem;font-size: 2.5vh">{{message.message}}</div> <!-- <div style="font-size: 1.8vh;margin-left: 0.5rem;color: gray;margin-top: 0.2rem">--> <!-- <span v-if="true">已读</span>--> <!-- <span v-if="false">未读</span>--> <!-- </div>--> </div> </div> </div> </div> <div style="width: 100%;height: 4vh"></div> </div> <div v-if="name!=''" style="clear: left;position:absolute;bottom: 10px;width: 100%;height: 5vh;background-color: white"> <input v-model="message" type="text" name="message" style="float: left;width: 55%;margin-left: 7vw;height: 4.7vh;border-radius: 0.5rem;"> <div style="float: left"> <input @click="addMessage" value="发送" type="button" style="height: 5vh;width: 5vw;border-radius: 0.5rem;margin-left: 0.7vw; font-size: 2.5vh;margin-top: 0.1vh;"/> </div> </div> </div> </div>
js部分
mounted部分:页面加载就连接,然后就实时接收消息
mounted() { var socket = new WebSocket("ws://localhost:8818/ws/2"); console.log(this) const data = this; socket.onmessage = function(event) { data.setMessage( name, event.data ) console.log("收到服务器消息: " + event.data); console.log(data); }; },
方法部分
// 接收消息 setMessage(name,message){ console.log(this.list) //date: "2023-10-26T14:06:06.387", read: 0, sender: "李四", name: "张三", id: 1, message: "你好2 this.list.push({date: new Date(),read: 0,sender: this.userName,name: name,id: this.list.length+1, message: message }) this.getMessages(); },
// 发送消息 addMessage(){ var i =1; console.log(this.list) const message = this.message; if (message!=null&&message!=''){ this.$http.post('/api/cloud-member/member/webSocket',{ 'id': this.id,'message':message,'name':this.name,sender: this.userName }).then(response => { console.log(response); if (i<=1){ // 请求成功处理 this.getMessages(); const date = new Date(); console.log(new Date()); console.log(this.date); if (date.getTime()-this.date>=300000){ var month = date.getMonth() + 1 const year = date.getFullYear()+"-"+month+"-"+date.getDate()+" " +date.getHours()+":"+date.getMinutes(); this.list.push({date: year, read: 0,sender: this.userName, name: this.name, id: this.list.length+1, message: message}); }else{ this.list.push({date: '', read: 0,sender: this.userName, name: this.name, id: this.list.length+1, message: message}); } // this.getMessage({name: this.userName,sender: this.name}) i++; } }).catch(error => { // 请求失败处理 console.log(error); }); } this.message = ''; },
getMessage(name){ // console.log(name); // this.getMessages(); this.name = name.sender this.list = []; }, // 修改时间 getDateTime(name){ this.lists.forEach(list=>{ if ((list.sender==name.sender&&list.name==name.name)||(list.sender==name.name&&list.name==name.sender)){ // 5分钟 300000 let date = new Date(list.date).getTime(); console.log(date) if (date-this.date>300000){ this.date = date; list.date = list.date.substring(0,16).replace('T',' '); // if (id==1){ // //date: "2023-10-26T14:06:06.387", read: 0, sender: "李四", name: "张三", id: 1, message: "你好2 // this.list.push({date: item.date,read: item.read,sender: this.userName,name: this.name,id: this.list.length+1, message: item.message,}) // } }else{ list.date = ''; } //date: "2023-10-26T14:06:06.387", read: 0, sender: "李四", name: "张三", id: 1, message: "你好2 this.list.push({date: list.date, read: 0,sender: list.sender, name: list.name, id: this.list.length+1, message: list.message}); console.log(this.list) } }) }, getStyMessage(name){ // console.log(name); this.getMessages(); this.name = name.sender this.list = []; this.getStyle(name.id) this.getDateTime(name); },
// 消息列表选中变颜色 getStyle(id){ let classNames = document.getElementsByClassName("messagediv"); for (let i = 0; i < classNames.length; i++) { classNames[i].style.backgroundColor = "white" } const ids = document.getElementById("id"+id); ids.style.backgroundColor = "#e1e1e1"; }, getMessages(){ this.$http.get('/api/cloud-member/member/getMessage/'+this.userName).then(response => { // console.log(Array.from(response.data.data)); const m = response.data.data; if (Array.from(m).length>0){ const list = Array.from(response.data.data); this.lists = list; } this.userList = []; const set = new Set(); this.lists.forEach(item=>{ // 必须要跟我聊过天的才显示 过滤掉自己 if (item.sender==this.userName||item.name==this.userName){ if (item.sender!=this.userName){ set.add(item.sender) } } }) const name = Array.from(set) for (let i = 0; i < name.length; i++) { this.userList.push({id: i+1,sender: name[i],name:this.userName}); } }).catch(error => { // 请求失败处理 console.log(error); }); }
后端java代码
websocket类
/** * WebSocket服务 */ @Component @ServerEndpoint("/ws/{sid}") public class WebSocketServer { //存放会话对象 private static Map<String, Session> sessionMap = new HashMap(); private Map<String, Object> map = new HashMap(); private List<String> list = new ArrayList<>(); /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { System.out.println("客户端:" + sid + "建立连接"); list.add(session.getId()); sessionMap.put(sid, session); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, @PathParam("sid") String sid) { map.put(sid,(map.get(sid)==null?"":(map.get(sid)+","))+message); System.out.println("收到来自客户端:" + sid + "的信息:" + map); } /** * 连接关闭调用的方法 * * @param sid */ @OnClose public void onClose(@PathParam("sid") String sid) { System.out.println("连接断开:" + sid); sessionMap.remove(sid); } /** * 群发 * * @param message */ public void sendToAllClients(String message) { Collection<Session> sessions = sessionMap.values(); for (Session session : sessions) { try { //服务器向客户端发送消息 session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } /** * 私发 * * @param message */ public void sendToAllClient(String id,String message) { Session session = sessionMap.get(id); if (session != null) { try { // 向客户发送消息 session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } else { System.out.println("找不到该客户的会话信息"); } } }
websocket配置类
/** * @Author: xhj * @Date: 2023/10/23/20:15 * @Description: */ /** * WebSocket配置类,用于注册WebSocket的Bean */ @Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
发送消息
@PostMapping("/webSocket") public R webSocket(@RequestBody Map<String,Object> objectMap){ // Map<String, Object> map = new HashMap<>(); // map.put("id",objectMap.get("id")); // map.put("message",objectMap.); // map.put("sender",sender); // map.put("name",name); objectMap.put("date", LocalDateTime.now()); objectMap.put("read",0); //基于WebSocket实现发送消息 webSocketServer.sendToAllClient(objectMap.get("id")+"", objectMap.get("message")+""); objectMap.put("id",list.size()+1); list.add(objectMap); return R.ok(list); }
获取消息
@GetMapping("/getMessage/{sender}") public R getMessage(@PathVariable("sender") String sender){ List<Map<String,Object>> list1 = new ArrayList<>(); for (Map<String, Object> map : list) { if (map.get("sender").equals(sender)||map.get("name").equals(sender)){ list1.add(map); } } System.out.println(list1); return R.ok(list1); }
因为没有对接数据库所以我就使用了map来放数据
private List<Map<String,Object>> list = new ArrayList<>(); public MemberController(){ HashMap<String, Object> map = new HashMap<>(); map.put("id",this.list.size()+1); map.put("message","你好2"); map.put("sender","李四"); map.put("name","张三"); map.put("date", LocalDateTime.now()); map.put("read",0); HashMap<String, Object> map2 = new HashMap<>(); map2.put("id",this.list.size()+1); map2.put("message","你好2"); map2.put("sender","张三"); map2.put("name","李四"); map2.put("date", LocalDateTime.now()); map2.put("read",0); HashMap<String, Object> map3 = new HashMap<>(); map3.put("id",this.list.size()+1); map3.put("message","你好2"); map3.put("sender","张三"); map3.put("name","王五"); map3.put("date", LocalDateTime.now()); map3.put("read",0); list.add(map); list.add(map2); list.add(map3); }
现在能简单的通讯了,最重要的是理解,有可能放入你的电脑执行会有bug
如果你对接数据库,前端就不需要写这么麻烦了
后续我对此进行了优化和对接数据库,最重要的就是websocket类里面的几个方法,最后我前端写了个websocket.js,全局使用。