牛逼,spring boot+vue实现H5聊天室客服功能 (附源码)

共 12254字,需浏览 25分钟

 ·

2021-11-20 06:33

h5效果图

vue效果图

功能实现

  • spring boot + webSocket 实现

  • 官方地址 https://docs.spring.io/spring-framework/docs/5.0.8.RELEASE/spring-framework-reference/web.html#websocket

maven 配置文件

"1.0" encoding="UTF-8"?>
"http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.0.0
    
        org.springframework.boot
        spring-boot-dependencies
        2.2.0.RELEASE
    

    org.example
    webChat
    1.0-SNAPSHOT
    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

        
            com.alibaba
            fastjson
            1.2.78
        


        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-websocket
        

        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        

                    

                

            

        

    



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
@EnableWebSocket
public 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 userMap = new ConcurrentHashMap<>(); // 用户
    private static Map 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 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 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 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服务端



 
  "utf-8">
  服务端
  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;
   }
  
 
 
  "client">
   "text-align: center;">服务端发送消息
   "content" contenteditable=true
    style="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;">

   

   "padding: 5px;0px">
    type="" value="" /> "button" type="button">发送
   

  

  
  
 

客户端



 
  "utf-8">
  客户端
  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;
   }
  
 
 
  "client">
   "text-align: center;">客户端发送消息
   "content" contenteditable=true
    style="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;">

   

   "padding: 5px;0px">
    type="" value="" /> "button" type="button">发送
   

  
  
  
 

vue 连接 webSocket







源码地址 

https://gitee.com/bxmms/web-chat.git


  作者 |  天葬

来源 |  cnblogs.com/bxmm/p/15552285.html


加锋哥微信: java1239  
围观锋哥朋友圈,每天推送Java干货!

浏览 187
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报