html5客服系统源码(客服系统源码)

h5效果图

html5客服系统源码(客服系统源码)(1)

h5页面聊天

vue效果图

html5客服系统源码(客服系统源码)(2)

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

    分享
    投诉
    首页