栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

基于websocket实现一个简单的网站在线客服聊天室案例

Java 更新时间:发布时间: 百科书网 趣学号
前言

 

在网站项目开发中,我们经常会有在线客服的功能,通过网站开启一个聊天室,进行客服解答功能,本节我们使用websocket实现一个简单的网站在线客服聊天功能,效果如下:

正文
  • 后端引入websocket的pom依赖

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

  •  后端初始化注入websocket的ServerEndpointExporter端点
package com.yundi.atp.platform.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

  •  后端创建一个websocket服务器,用于前后端通信,发送消息
package com.yundi.atp.platform.websocket;

import com.alibaba.fastjson.JSON;
import com.yundi.atp.platform.module.test.entity.ChatMsg;
import com.yundi.atp.platform.module.test.service.ChatMsgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


@Slf4j
@Component
@ServerEndpoint("/websocket/chat/{userName}")
public class WebSocketServer {
    private Session session;

    private static CopyOnWriteArraySet webSockets = new CopyOnWriteArraySet<>();

    private static Map sessionPool = new ConcurrentHashMap<>();

    private static ChatMsgService chatMsgService;

    private static String SUPER_ADMIN = "super_admin";

    @Autowired
    public void setWebSocketServer(ChatMsgService chatMsgService) {
        WebSocketServer.chatMsgService = chatMsgService;
    }

    @onOpen
    public void onOpen(Session session, @PathParam(value = "userName") String userName) {
        List onlineList = new ArrayList<>();
        this.session = session;
        webSockets.add(this);
        sessionPool.put(userName, session);
        log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
        Iterator> iterator = sessionPool.entrySet().iterator();
        while (iterator.hasNext()) {
            onlineList.add(iterator.next().getKey());
        }
        onlineList.remove(SUPER_ADMIN);
        Map map = new HashMap<>(16);
        map.put("key", 1);
        map.put("onlineList", onlineList);
        map.put("userList", chatMsgService.getUserList());
        this.sendoneMessage(SUPER_ADMIN, JSON.toJSonString(map));
    }

    @onClose
    public void onClose(@PathParam(value = "userName") String userName) {
        webSockets.remove(this);
        sessionPool.remove(userName);
        log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
        List onlineList = new ArrayList<>();
        Iterator> iterator = sessionPool.entrySet().iterator();
        while (iterator.hasNext()) {
            onlineList.add(iterator.next().getKey());
        }
        onlineList.remove(SUPER_ADMIN);
        Map map = new HashMap<>(16);
        map.put("key", 2);
        map.put("onlineList", onlineList);
        map.put("userList", chatMsgService.getUserList());
        this.sendoneMessage(SUPER_ADMIN, JSON.toJSonString(map));
    }

    @onMessage
    public void onMessage(String message) {
        ChatMsg chatMsg = JSON.parseObject(message, ChatMsg.class);
        chatMsgService.save(chatMsg);
        Map map = new HashMap<>(16);
        map.put("key", 3);
        map.put("data", chatMsg);
        this.sendoneMessage(chatMsg.getSender(), JSON.toJSonString(map));
        this.sendoneMessage(chatMsg.getReceiver(), JSON.toJSonString(map));
    }

    
    public void sendAllMessage(String message) {
        for (WebSocketServer webSocket : webSockets) {
            log.info("【websocket消息】广播消息:" + message);
            try {
                webSocket.session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    
    public void sendoneMessage(String userName, String message) {
        log.info("【websocket消息】单点消息:" + message);
        Session session = sessionPool.get(userName);
        if (session != null) {
            try {
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

  • 后端聊天室功能控制层接口
package com.yundi.atp.platform.module.test.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yundi.atp.platform.common.Result;
import com.yundi.atp.platform.module.test.entity.ChatMsg;
import com.yundi.atp.platform.module.test.service.ChatMsgService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Api(tags = "聊天室接口")
@RestController
@RequestMapping("/test/chatMsg")
public class ChatMsgController {
    @Autowired
    private ChatMsgService chatMsgService;

    @ApiOperation(value = "获取聊天室地址")
    @GetMapping(value = "/getWebSocketAddress/{username}")
    public Result getWebSocketAddress(HttpServletRequest request, @PathVariable(value = "username") String username) throws UnknownHostException {
        String address = "ws://" + InetAddress.getLocalHost().getHostAddress() + ":" + request.getServerPort() + request.getContextPath() + "/websocket/chat/" + username;
        return Result.success(address);
    }

    @ApiOperation(value = "获取历史聊天记录")
    @GetMapping(value = "/getHistoryChat/{username}")
    public Result getWebSocketAddress(@PathVariable(value = "username") String username) {
        List list = chatMsgService.list(new QueryWrapper()
                .and(wrapper -> wrapper.eq("sender", username).or().eq("receiver", username))
                .orderByDesc("create_time"));
        List collect = list.stream().sorted(Comparator.comparing(ChatMsg::getCreateTime)).collect(Collectors.toList());
        return Result.success(collect);
    }

    @ApiOperation(value = "获取用户列表")
    @GetMapping(value = "/getUserList")
    public Result getUserList() {
        List userList = chatMsgService.getUserList();
        return Result.success(userList);
    }

}

  •  后端聊天室功能业务层
package com.yundi.atp.platform.module.test.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yundi.atp.platform.module.test.entity.ChatMsg;
import com.yundi.atp.platform.module.test.mapper.ChatMsgMapper;
import com.yundi.atp.platform.module.test.service.ChatMsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class ChatMsgServiceImpl extends ServiceImpl implements ChatMsgService {
    @Autowired
    private ChatMsgMapper chatMsgMapper;

    @Override
    public List getUserList() {
        List userList = chatMsgMapper.getUserList();
        return userList;
    }
}

  •   后端聊天室功能持久层
package com.yundi.atp.platform.module.test.mapper;

import com.baomidou.mybatisplus.core.mapper.baseMapper;
import com.yundi.atp.platform.module.test.entity.ChatMsg;

import java.util.List;


public interface ChatMsgMapper extends baseMapper {
    
    List getUserList();

}

  •  后端聊天室功能持久层Mapper




    
        SELECT sender FROM `chat_msg` where sender != 'super_admin' GROUP BY sender
    

  •   前端聊天室功能页面





.container {
  padding-top: 50px;

  .box-card {
    margin: auto;
    width: 800px;
    height: 800px;
    max-height: 900px;

    ::v-deep .el-card__header {
      background: #867ba9 !important;
      border-bottom: none;
      padding: 0;
    }

    ::v-deep .el-card__body {
      padding: 0px !important;
      position: relative;

      .content {
        height: 600px;
        background: #ddd;
        overflow-y: auto;

        .el-divider--horizontal {
          margin: 0;
        }

        .active {
          color: #0080ff;
        }

        .mark {
          background: #deb068;
        }

        .item {
          margin-top: 10px;
          margin-right: 10px;
        }
      }

      .operate {
        padding: 5px 15px;
      }
    }
  }
}

  •  聊天室页面效果

结语

本节内容到这里就结束了,我们下期见。。。

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/275221.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号