前言
最近项目中要实现客服系统,其实网上有很多的服务商提供这种接口,但最终决定使用SpringBoot+WebSocket的方式实现。
下面我的项目的结构是使用SpringBoot+Nginx实现的前后端分离的,但是这个不重要,这里只是提出来。
SpringBoot和Nginx我就不在这里多说了,网上有很多教程。过几天我也会专门写几篇文章记录一下。
1. 后台代码
在pom.xml中添加spring-boot-starter-websocket
<!--WebSocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
添加配置,先在src\main\resources\application.yml中添加:
server:
port: 8085
servlet:
context-path: /yblog
max-http-header-size: 8192
最主要是最后一行,如果不加的话可能导致无法进行访问。
在启动类或者新建一个配置类,主要一个Bean,用来启动服务是也启动WebSocket服务:
//WebSocket
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
注意:这个类必须有@Configuration注解
然后新建一个model来封装进行对话的对象,我一直在纠结到底要不要这个类,最后决定要,这样可以避免很多麻烦。
public class SocketUserInfo {
//用户sessionId
private String sessionId;
//用户session
private Session session;
//目标用户sessionid
private String targetSessionId;
//用户角色
private String userRole;
public String getUserRole() {
return userRole;
}
public void setUserRole(String userRole) {
this.userRole = userRole;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public String getTargetSessionId() {
return targetSessionId;
}
public void setTargetSessionId(String targetSessionId) {
this.targetSessionId = targetSessionId;
}
}
新建一个类来管理Socket会话,这个类我也不清楚该是Service还是Controller,最后我把它作为了Controller,因为我觉得它更像一个Controller。它主要完成如下场景业务:
- 用户连接上线:如果是一个客服上线,就保存一个客服信息,同时去查找有没有再排队中的用户,如果有就给他们俩建立会话关系;如果是一个用户上线,先建立保存用户信息,再去查找有没有空闲客服,如果有就建立会话关系,如果没有就告诉他系统繁忙,让他进入等待状态。
- 用户下线:如果是客户下线,就删除客服信息,为了方便,我直接让用户刷新页面重新匹配客服,其实这样做不是很好;如果是用户下线,就删除用户信息,让空闲下来的客服和排队中的用户建立会话关系
。- 发送消息:如果是用户发的消息,就将消息推送给相应客服;如果是客服发的消息,就推送给相应用户。
//参数role判断用户角色0是客服,1是用户
@ServerEndpoint(value = "/websocket/{role}")
@Component
public class SocketController {
//用本地线程保存session
private static ThreadLocal<Session> sessions = new ThreadLocal<Session>();
//保存所有连接上的用户的session
private static Map<String, SocketUserInfo> userSessionMap = new ConcurrentHashMap<>();
//保存在线客服的session
private static Map<String, SocketUserInfo> serverSessionMap = new ConcurrentHashMap<>();
//连接
@OnOpen
public void onOpen(Session session, @PathParam(value="role") Integer role) {
//默认返回错误状态
Map<String, String> resultMap = new HashMap<>();
resultMap.put("state", "error");
//保证各个线程里的变量相对独立于其他线程内的变量
sessions.set(session);
//客服上线
if (role.equals(0)) {
//创建一个在线客服信息
SocketUserInfo serverInfo = new SocketUserInfo();
serverInfo.setSessionId(session.getId());
serverInfo.setSession(session);
serverInfo.setUserRole("客服");
//告诉客服连接成功
resultMap.put("state", "success");
//去查询是否有排队中的用户
//如果存在排队的用户,就将用户和客服绑定
if (findLineUser() != null){
SocketUserInfo userInfo = userSessionMap.get(findLineUser());
//将用户绑定到客服
serverInfo.setTargetSessionId(userInfo.getSessionId());
//将客服绑定到用户
userInfo.setTargetSessionId(serverInfo.getSessionId());
userSessionMap.put(userInfo.getSessionId(), userInfo);
System.out.println("客户"+ serverInfo.getSessionId() + "正在为用户" + userInfo.getSessionId()+"服务");
Map<String, String> result = new HashMap<>();
//客服显示用户信息
result.put("msg", "正在为用户"+userInfo.getSessionId()+"服务!");
sendMsg(serverInfo.getSession(), JSON.toJSONString(result));
//告诉用户有客服为他服务
result.put("msg", "客服"+serverInfo.getSessionId()+"正在为您服务!");
SpringBoot WebSocket 客服系统

本文介绍如何使用SpringBoot和WebSocket实现客服系统的前后端分离,包括后台代码配置和前端连接、消息收发的实现。
最低0.47元/天 解锁文章
1515

被折叠的 条评论
为什么被折叠?



