One, foreword
This article will be based on SpringBoot + Vue + WebSocket to achieve a simple online chat function
The page is as follows:
Online experience address: www.zhengqingya.com:8101
Second,SpringBoot
+ Vue
+ WebSocket
Enabling online chat
1. Introduce webSocket dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>Copy the code
2. Websocket configuration class
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}Copy the code
Websocket handles the Controller class
@ Slf4j @ Component @ ServerEndpoint ("/groupChat / {sid} / {username} ") public class WebSocketServerController {/ * * * room number - > */ private static ConcurrentHashMap<String, List<Session>> groupMemberInfoMap = new ConcurrentHashMap<>(); Private static ConcurrentHashMap<String, Set<Integer>> onlineUserMap = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, Set<Integer>> onlineUserMap = new ConcurrentHashMap<>(); @param sid: room number * @param userId: userId * @param message: */ @onMessage Public void OnMessage (@pathParam ("sid") String SID, @pathParam ("userId") Integer userId, String message) { List<Session> sessionList = groupMemberInfoMap.get(sid); Set<Integer> onlineUserList = onlineUserMap.get(sid); SessionList. ForEach (item -> {try {// json string turn object MsgVO = jsonObject.parseObject (message, MsgVO.class); msg.setCount(onlineUserList.size()); String text = jsonObject.tojsonString (MSG); item.getBasicRemote().sendText(text); } catch (IOException e) { e.printStackTrace(); }}); } /** * the method that establishes the connection call, * * @param session @param sid */ @onopen public void OnOpen (session session, @pathParam ("sid") String sid, @PathParam("userId") Integer userId) { List<Session> sessionList = groupMemberInfoMap.computeIfAbsent(sid, k -> new ArrayList<>()); Set<Integer> onlineUserList = onlineUserMap.computeIfAbsent(sid, k -> new HashSet<>()); onlineUserList.add(userId); sessionList.add(session); SendInfo (sid, userId, onlineUserlist.size (), "online ~"); } public void sendInfo(String sid, Integer userId, Integer onlineSum, String info) {// Get the connection User information User currentUser = ApplicationContextUtil.getApplicationContext().getBean(UserMapper.class).selectById(userId); MsgVO = new MsgVO(); msg.setCount(onlineSum); msg.setUserId(userId); msg.setAvatar(currentUser.getAvatar()); msg.setMsg(currentUser.getNickName() + info); String text = jsonObject.tojsonString (MSG); onMessage(sid, userId, text); } /** * close the method called by the connection, @param session * @param sid */ @onclose public void OnClose (session session, @pathParam ("sid") String sid, @PathParam("userId") Integer userId) { List<Session> sessionList = groupMemberInfoMap.get(sid); sessionList.remove(session); Set<Integer> onlineUserList = onlineUserMap.get(sid); onlineUserList.remove(userId); SendInfo (sid, userId, onlineUserlist.size (), "offline ~"); } /** * @param error */ @onError public void OnError(Throwable error) {log.info("Connection error"); }}Copy the code
4. Websocket message display class
@data @APIModel (description = "webSocket message content ") public class MsgVO {@APIModelProperty (value =" user ID ") private Integer userId; @apiModelProperty (value = "username ") private String username; @APIModelProperty (value = "user avatar ") private String avatar; @apiModelProperty (value = "message ") private String MSG; @apiModelProperty (value = "online number ") private int count; }Copy the code
5. Front-end page
Tips: When the user login successfully, can initiate websocket connection, stored in the store…
The following is a simple implementation of a single page
<template> <div class="chat-box"> <header> </header> <div class="msg-box" ref="msg-box"> <div v-for="(i,index) in list" :key="index" class="msg" :style="i.userId == userId? 'flex-direction:row-reverse':''" > <div class="user-head"> <img :src="i.avatar" height="30" width="30" :title="i.username"> </div> <div class="user-msg"> <span :style="i.userId == userId? ' float: right; ':''" :class="i.userId == userId? 'right':'left'">{{i.content}}</span> </div> </div> </div> <div class="input-box"> <input type="text" ref="sendMsg" v-model="contentText" @keyup.enter="sendText()" /> <div class="btn" :class="{['btn-active']:contentText}" @click="sendText()"> send </div> </div> </div> </template> <script> export default {data() {return {ws: null, count: $store.getters.id, userId: this.$store.getters.id, userId: this.$store.getters.name, // Avatar: This.$store.getters. Avatar, // list: [], // Array of chat entries contentText: "" // input input values}; }, mounted() { this.initWebSocket(); }, destroyed() {// Close webSocket connection this.ws. Onclose (undefined); }, methods: {sendText() {let _this = this; _this.$refs["sendMsg"].focus(); if (! _this.contentText) { return; } let params = { userId: _this.userId, username: _this.username, avatar: _this.avatar, msg: _this.contentText, count: _this.count }; _this.ws.send(JSON.stringify(params)); ContentText = ""; // Call WebSocket send(). setTimeout(() => { _this.scrollBottm(); }, 500); }, // go to the page to create a websocket connection initWebSocket() {let _this = this; If (window.websocket) {var serverHot = window.location.hostname; Let sip = 'room number' // Enter the local IP address :9101 Port number must be the same as that configured on the back end! var url = 'ws://' + serverHot + ':9101' + '/groupChat/' + sip + '/' + this.userId; / / ` ws: / / 127.0.0.1/9101 / groupChat / 10086 / chat room ` let ws = new WebSocket (url); _this.ws = ws; Ws. onopen = function(e) {console.log(" server connected successfully: "+ url); }; Ws. onclose = function(e) {console.log(" server connection closed: "+ url); }; Ws.onerror = function() {console.log(" server connection error: "+ url); }; Ws.onmessage = function(e) {let resData = json.parse (e.data) _this.count = resdata.count; _this.list = [ ..._this.list, { userId: resData.userId, username: resData.username, avatar: resData.avatar, content: resData.msg } ]; }; }, // scrollBottm() {let el = this.$refs["msg-box"]; el.scrollTop = el.scrollHeight; }}}; </script> <style lang="scss" scoped> .chat-box { margin: 0 auto; background: #fafafa; position: absolute; height: 100%; width: 100%; max-width: 700px; header { position: fixed; width: 100%; height: 3rem; background: #409eff; max-width: 700px; display: flex; justify-content: center; align-items: center; font-weight: bold; color: white; font-size: 1rem; } .msg-box { position: absolute; Height: calc 100% 6.5 (rem); width: 100%; margin-top: 3rem; overflow-y: scroll; .msg { width: 95%; Min - height: 2.5 rem; Margin: 1 rem 0.5 rem. position: relative; display: flex; justify-content: flex-start ! important; . The user - head {min - width: 2.5 rem; width: 20%; Width: 2.5 rem; Height: 2.5 rem; border-radius: 50%; background: #f1f1f1; display: flex; justify-content: center; align-items: center; The head {width: 1.2 rem; Height: 1.2 rem; } // position: absolute; } .user-msg { width: 80%; // position: absolute; word-break: break-all; position: relative; z-index: 5; span { display: inline-block; Padding: 0.5 rem 0.7 rem; Border - the radius: 0.5 rem; Margin - top: 0.2 rem; The font - size: 0.88 rem; } .left { background: white; Animation: toLeft 0.5s ease both 1; } .right { background: #53a8ff; color: white; Animation: Toright 0.5s ease both 1; } @keyframes toLeft { 0% { opacity: 0; transform: translateX(-10px); } 100% { opacity: 1; transform: translateX(0px); } } @keyframes toright { 0% { opacity: 0; transform: translateX(10px); } 100% { opacity: 1; transform: translateX(0px); }}}}}. Input-box {padding: 0 0.5rem; position: absolute; bottom: 0; width: 100%; Height: 3.5 rem; background: #fafafa; box-shadow: 0 0 5px #ccc; display: flex; justify-content: space-between; align-items: center; Input {height: 2.3 rem; display: inline-block; width: 100%; Padding: 0.5 rem; border: none; Border - the radius: 0.2 rem; The font - size: 0.88 rem; }. BTN {height: 2.3rem; min-width: 4rem; background: #e0e0e0; Padding: 0.5 rem; The font - size: 0.88 rem; color: white; text-align: center; Border - the radius: 0.2 rem; Margin - left: 0.5 rem; The transition: 0.5 s; } .btn-active { background: #409eff; } } } </style>Copy the code
This article case demo source
Gitee.com/zhengqingya…