html5客服系统源码(客服系统源码)
h5效果图
h5页面聊天
vue效果图
vue页面聊天
功能实现
- spring boot + webSocket 实现
- 官方地址 http://docs.spring.io/spring-framework/docs/5.0.8.RELEASE/spring-framework-reference/web.html#websocket
maven 配置文件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
webSocket 配置
package com.example.webchat.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;/** * @author Mr.Fang * @title: WebSocketConfig * @Description: web socket 配置 * @date 2021/11/14 13:12 */@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "myHandler/") // 访问路径 .addInterceptors(new WebSocketHandlerInterceptor()) // 配置拦截器 .setAllowedOrigins("*"); // 跨域 } @Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); // 例如消息缓冲区大小、空闲超时等 container.setMaxBinaryMessageBufferSize(8192); return container; } @Bean public WebSocketHandler myHandler() { return new MyHandler(); }}
消息处理类
package com.example.webchat.config;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.example.webchat.pojo.DataVo;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.io.IOException;import java.util.*;import java.util.concurrent.ConcurrentHashMap;/** * @author Mr.Fang * @title: MyHandler * @Description: 消息处理类 * @date 2021/11/14 13:12 */public class MyHandler extends AbstractWebSocketHandler { private static int onlineCount = 0; // 线程安全 private static Map<String, WebSocketSession> userMap = new ConcurrentHashMap<>(); // 用户 private static Map<String, WebSocketSession> adminMap = new ConcurrentHashMap<>(); // 客服 /** * @Description: 连接成功之后 * @param session * @return void * @Author Mr.Fang * @date 2021/11/14 13:15 */ @Override public void afterConnectionEstablished(WebSocketSession session) throws IOException { addOnlineCount(); // 当前用户加 1 System.out.println(session.getId()); Map<String, Object> map = session.getAttributes(); Object token = map.get("token"); Object admin = map.get("admin"); DataVo dataVo = new DataVo(); dataVo.setCode(9001).setMsg("连接成功"); if (Objects.nonNull(admin)) { adminMap.put(session.getId(), session); // 添加客服 } else { // 分配客服 userMap.put(session.getId(), session); // 添加当前用户 distribution(dataVo); } dataVo.setId(session.getId()); System.out.println("用户连接成功:" + admin); System.out.println("用户连接成功:" + token); System.out.println("在线用户:" + getOnlineCount()); this.sendMsg(session, JSONObject.toJSONString(dataVo)); } /** * @param vo * @return void * @Description: 分配客服 * @Author Mr.Fang * @date 2021/11/14 13:13 */ private void distribution(DataVo vo) { if (adminMap.size() != 0) { Random random = new Random(); int x = random.nextInt(adminMap.size()); Set<String> values = adminMap.keySet(); int j = 0; for (String str : values) { if (j == x) { vo.setRecId(str); System.out.println("分配ID:" + str); break; } j++; } } } /** * @param session * @param message * @return void * @Description: 收发消息 * @Author Mr.Fang * @date 2021/11/14 13:13 */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { System.out.print("用户ID:" + session.getId()); String payload = message.getPayload(); System.out.println("接受到的数据:" + payload); DataVo dataVo = JSON.toJavaObject(JSON.parseObject(payload), DataVo.class); // json 转对象 if (Objects.isNull(dataVo.getRecId()) || dataVo.getRecId().equals(")) { // 用户客服为空 分配客服 WebSocketSession socketSession = adminMap.get(session.getId()); if (Objects.isNull(socketSession)) { this.distribution(dataVo); } } if (dataVo.getCode() == 9002) { if (Objects.nonNull(dataVo.getRecId())) { // user -> admin WebSocketSession socketSession = adminMap.get(dataVo.getRecId()); dataVo.setSelfId(session.getId()).setRecId("); this.sendMsg(socketSession, JSONObject.toJSONString(dataVo)); } else if (Objects.nonNull(dataVo.getSelfId())) { // admin ->user WebSocketSession socketSession = userMap.get(dataVo.getSelfId()); dataVo.setRecId(session.getId()).setSelfId("); this.sendMsg(socketSession, JSONObject.toJSONString(dataVo)); } } } /** * @param session * @param msg * @return void * @Description: 发送消息 * @Author Mr.Fang * @date 2021/11/14 13:14 */ private void sendMsg(WebSocketSession session, String msg) throws IOException { session.sendMessage(new TextMessage(msg)); } /** * @Description: 断开连接之后 * @param session * @param status * @return void * @Author Mr.Fang * @date 2021/11/14 13:14 */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { subOnlineCount(); // 当前用户加 1 adminMap.remove(session.getId()); userMap.remove(session.getId()); System.out.println("用户断开连接token:" + session.getId()); System.out.println("用户断开连接admin:" + session.getId()); System.out.println("在线用户:" + getOnlineCount()); } public static synchronized int getOnlineCount() { return onlineCount; } /** * @Description: 在线用户 +1 * @return void * @Author Mr.Fang * @date 2021/11/14 13:16 */ public static synchronized void addOnlineCount() { MyHandler.onlineCount++; } /** * @Description: 在线用户 -1 * @return void * @Author Mr.Fang * @date 2021/11/14 13:16 */ public static synchronized void subOnlineCount() { MyHandler.onlineCount--; }}
配置拦截器
package com.example.webchat.config;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import javax.servlet.http.HttpServletRequest;import java.util.Map;import java.util.Objects;/** * @author Mr.Fang * @title: WebSocketHandlerInterceptor * @Description: 拦截器 * @date 2021/11/14 13:12 */public class WebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor { /** * @param request * @param response * @param wsHandler * @param attributes * @return boolean * @Description: 握手之前 * @Author Mr.Fang * @date 2021/11/14 13:18 */ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpServletRequest re = servletRequest.getServletRequest(); Object token = re.getParameter("token"); Object admin = re.getParameter("admin"); if (Objects.isNull(token)) { return false; } re.getSession().setAttribute("admin", admin); re.getSession().setAttribute("token", token); return super.beforeHandshake(request, response, wsHandler, attributes); } /** * @param request * @param response * @param wsHandler * @param ex * @return boolean * @Description: 握手之后 * @Author Mr.Fang * @date 2021/11/14 13:18 */ @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); }}
h5服务端
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>服务端</title> <style type="text/css"> #client { margin: 0px auto; width: 500px; } input { width: 80%; height: 40px; border-radius: 5px; border-color: #CCCCCC; outline: #01FA01; } #button { width: 84px; height: 46px; background-color: #5af3a5; color: #fff; font-size: 20px; border-radius: 5px; border: none; box-shadow: 1px 1px 1px 1px #ccc; cursor: pointer; outline: #01FA01; } </style> </head> <body> <div id="client"> <h1 style="text-align: center;">服务端发送消息</h1> <div id="content" contenteditable=true style="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"> </div> <div style="padding: 5px;0px"> <input type=" value=" /> <button id="button" type="button">发送</button> </div> </div> <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> $(() => { var pushData = { code: 9002, msg: '', selfId: '', }; var time = null; var path = 'ws://127.0.0.1:8009/myHandler/'; if (typeof(WebSocket) === "undefined") { alert('不支持websocket') return; } let id = Math.random(); // 随机数 // 实例化socket var webSocket = new WebSocket(path + '?token=' + id+'&admin=1'); // 监听连接 webSocket.onopen = function(event) { console.log(event); interval(); }; // 监听消息 webSocket.onmessage = function(event) { let data = JSON.parse(event.data); pushData.selfId = data.selfId; if (data.code == 9002) { $('#content').append( `<p style="text-align: right;"><span style="color:chocolate;">${data.msg}</span>:客户端</p>` ) } else if (data.code == 9001) { $('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接成功</p>`); } console.log(event) }; // 监听错误 webSocket.onerror = function(event) { console.log(event) $('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接错误</p>`); clearInterval(); }; // 发送消息 $('#button').click(() => { let v = $('input').val(); if (v) { pushData.code = 9002; pushData.msg = v; webSocket.send(JSON.stri.jpg"y(pushData)); $('#content').append( `<p>服务端:<span style="color: blueviolet;">${v}</span></p>` ) $('input').val(''); } }) function interval() { time = setInterval(() => { pushData.code = 9003; pushData.msg = '心跳'; webSocket.send(JSON.stri.jpg"y(pushData)); }, 5000); } function clearInterval() { clearInterval(time); } }) </script> </body></html>
客户端
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>客户端</title> <style type="text/css"> #client { margin: 0px auto; width: 500px; } input { width: 80%; height: 40px; border-radius: 5px; border-color: #CCCCCC; outline: #01FA01; } #button { width: 84px; height: 46px; background-color: #5af3a5; color: #fff; font-size: 20px; border-radius: 5px; border: none; box-shadow: 1px 1px 1px 1px #ccc; cursor: pointer; outline: #01FA01; } </style> </head> <body> <div id="client"> <h1 style="text-align: center;">客户端发送消息</h1> <div id="content" contenteditable=true style="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"> </div> <div style="padding: 5px;0px"> <input type=" value=" /> <button id="button" type="button">发送</button> </div> </div> <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> $(() => { var pushData = { code: 9002, msg: '', recId: '', }; var time = null; var path = 'ws://127.0.0.1:8009/myHandler/'; if (typeof(WebSocket) === "undefined") { alert('不支持websocket') return; } let id = Math.random(); // 随机数 // 实例化socket var webSocket = new WebSocket(path + '?token=' + id); // 监听连接 webSocket.onopen = function(event) { console.log(event); interval(); }; // 监听消息 webSocket.onmessage = function(event) { let data = JSON.parse(event.data); if (data.code == 9002) { $('#content').append( `<p style="text-align: right;"><span style="color:chocolate;">${data.msg}</span>:服务端</p>` ) } else if (data.code == 9001) { $('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接成功</p>`); } console.log(event) }; // 监听错误 webSocket.onerror = function(event) { console.log(event) $('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接错误</p>`); clearInterval(); }; // 发送消息 $('#button').click(() => { let v = $('input').val(); if (v) { pushData.code = 9002; pushData.msg = v; webSocket.send(JSON.stri.jpg"y(pushData)); $('#content').append( `<p>客户端:<span style="color: blueviolet;">${v}</span></p>` ) $('input').val(''); } }) function interval() { time = setInterval(() => { pushData.code = 9003; pushData.msg = '心跳'; webSocket.send(JSON.stri.jpg"y(pushData)); }, 5000); } function clearInterval() { clearInterval(time); } }) </script> </body></html>
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com